題目傳送門php
題目描述:
背景
花神是神,一大癖好就是嘲諷大J,舉例以下:
「哎你傻不傻的!【hqz:大笨J】」
「這道題又被J屎過了!!」
「J這程序怎麼跑這麼快!J要逆襲了!」
……
描述
這一天DJ在給吾等衆蒟蒻講題,花神在一邊作題無聊,就跑到了一邊跟吾等衆蒟蒻一塊兒聽。如下是部分摘錄:
「J你在講什麼!」
「我在講XXX!」
「哎你傻不傻的!這麼麻煩,直接XXX再XXX就行了!」
「……」
「J你XXX講過了沒?」
「……」
「那個都不講你就講這個了?哎你傻不傻的!」
「……」
DJ對這種情景表示很是無語,往往出現這種狀況,DJ都是很是尷尬的。
↑廢話c++
通過衆蒟蒻研究,DJ在講課以前會有一個長度爲N方案,咱們能夠把它看做一個數列;
一樣,花神在聽課以前也會有一個嘲諷方案,有M個,每次會在x到y的這段時間開始嘲諷,爲了減小題目難度,每次嘲諷方案的長度是必定的,爲K。
花神嘲諷DJ讓DJ尷尬須要的條件:
在x~y的時間內DJ沒有講到花神的嘲諷方案,即J的講課方案中的x~y沒有花神的嘲諷方案【這樣花神會嘲諷J不會因此不講】。
通過衆蒟蒻努力,在一次講課以前獲得了花神嘲諷的各次方案,DJ得知了這個消息之後欣喜不已,DJ想知道花神的每次嘲諷是否會讓DJ尷尬【說不出話來】。
spa
輸入格式:
第1行3個數N,M,K;
第2行N個數,意義如上;
第3行到第3+M-1行,每行K+2個數,前兩個數爲x,y,而後K個數,意義如上; blog
輸出格式:
對於每個嘲諷作出一個回答會尷尬輸出‘Yes’,不然輸出‘No’get
樣例:
樣例輸入:
8 5 3
1 2 3 4 5 6 7 8
2 5 2 3 4
1 8 3 2 1
5 7 4 5 6
2 5 1 2 3
1 7 3 4 5
樣例輸出:
No
Yes
Yes
Yes
Nohash
數據範圍與提示:
題中全部數據不超過2*10^9;保證方案序列的每一個數字<=N,n,m<=1e5,k<=20
2~5中有2 3 4的方案,輸出No,表示DJ不會尷尬
1~8中沒有3 2 1的方案,輸出Yes,表示DJ會尷尬
5~7中沒有4 5 6的方案,輸出Yes,表示DJ會尷尬
2~5中沒有1 2 3的方案,輸出Yes,表示DJ會尷尬
1~7中有3 4 5的方案,輸出No,表示DJ不會尷尬
it
一句話題意:給你m個長度爲k的串,看這m個串有沒有在主串中出現。class
題解:
終於有親切的題解啦~
我感受這是一道不錯的題,真的是一秒出正解,hash+主席樹
可是……還有可是……
主席樹挺麻煩的,何況纔剛學,懶得碼,記得分塊也能夠幹這種事,並且還能求出現的次數。
太棒啦~~~
注意這道題k是同樣的,這樣就能允許咱們用分塊啦~~~
只須要暴力求出主串全部的hash值,放進咱們分好的塊中,再用這m個串逐一查找便可
時間複雜度n√n(剛恰好)
想到這種解法以爲本身都很牛逼程序
代碼時刻:數據
#include<bits/stdc++.h> using namespace std; int n,k,m,len; unsigned long long a[100001],b[100001],sum;//unsigned暴力卡hash int wzc(int x){return (x-1)/k+1;}//查找這個點屬於哪一個塊 void get_hash()//主串轉hash { for(int i=1;i<=n-len+1;i++) { unsigned long long sum=0; for(int j=i;j<=i+len-1;j++) sum=sum*131+a[j]; a[i]=b[i]=sum; } } bool ask(int l,int r,unsigned long long x)//查找有沒有出現 { int cl=wzc(l); int cr=wzc(r); if(cl==cr)for(int i=l;i<=r;i++)if(a[i]==x)return 1; for(int i=l;i<=cl*k;i++)if(a[i]==x)return 1; for(int i=cl+1;i<cr;i++)if(upper_bound(b+(i-1)*k+1,b+i*k+1,x)-lower_bound(b+(i-1)*k+1,b+i*k+1,x))return 1; for(int i=(cr-1)*k+1;i<=r;i++)if(a[i]==x)return 1; return 0; } int main() { scanf("%d%d%d",&n,&m,&len); for(int i=1;i<=n;i++) scanf("%d",&a[i]); get_hash(); n=n-len+1; k=sqrt(n); for(int i=1;i<=k+1;i++) { if((i-1)*k+1>n)break; sort(b+(i-1)*k+1,b+min(i*k,n)+1); } while(m--) { int l,r; scanf("%d%d",&l,&r); sum=0; for(int i=1;i<=len;i++) { int hs; scanf("%d",&hs); sum=sum*131+hs; } if(ask(l,r-len+1,sum))printf("No\n");//輸出要注意兩點:1.Yes和No別反了就好。2.注意大小寫!!!身邊好多同窗調了半天就由於這!!! else printf("Yes\n"); } return 0; }
cpp
rp++