BZOJ 3207: 花神的嘲讽计划Ⅰ
3207: 花神的嘲讽计划Ⅰ
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 2208 Solved: 807
[Submit][Status][Discuss]
Description
背景
花神是神,一大癖好就是嘲讽大J,举例如下:
“哎你傻不傻的!【hqz:大笨J】”
“这道题又被J屎过了!!”
“J这程序怎么跑这么快!J要逆袭了!”
……
描述
这一天DJ在给吾等众蒟蒻讲题,花神在一边做题无聊,就跑到了一边跟吾等众蒟蒻一起听。以下是部分摘录:
1.
“J你在讲什么!”
“我在讲XXX!”
“哎你傻不傻的!这么麻烦,直接XXX再XXX就好了!”
“……”
2.
“J你XXX讲过了没?”
“……”
“那个都不讲你就讲这个了?哎你傻不傻的!”
“……”
DJ对这种情景表示非常无语,每每出现这种情况,DJ都是非常尴尬的。
经过众蒟蒻研究,DJ在讲课之前会有一个长度为N方案,我们可以把它看作一个数列;
同样,花神在听课之前也会有一个嘲讽方案,有M个,每次会在x到y的这段时间开始嘲讽,为了减少题目难度,每次嘲讽方案的长度是一定的,为K。
花神嘲讽DJ让DJ尴尬需要的条件:
在x~y的时间内DJ没有讲到花神的嘲讽方案,即J的讲课方案中的x~y没有花神的嘲讽方案【这样花神会嘲讽J不会所以不讲】。
经过众蒟蒻努力,在一次讲课之前得到了花神嘲讽的各次方案,DJ得知了这个消息以后欣喜不已,DJ想知道花神的每次嘲讽是否会让DJ尴尬【说不出话来】。
Input
第1行3个数N,M,K;
第2行N个数,意义如上;
第3行到第3+M-1行,每行K+2个数,前两个数为x,y,然后K个数,意义如上;
Output
对于每一个嘲讽做出一个回答会尴尬输出‘Yes’,否则输出‘No’
Sample Input
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
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
Sample Output
No
Yes
Yes
Yes
No
Yes
Yes
Yes
No
HINT
题中所有数据不超过2*10^9;保证方案序列的每个数字<=N
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不会尴尬
Source
分析:
因为每一段的长度是固定的,所以我们可以把每一段Hash一下(顺便离散化一下),用主席树维护出现次数,查询当前区间内是否存在这个Hash值...
一开始我很智障地把i~j的Hash值在i~j每个位置的线段树中都+1...强行增加复杂度...
代码:
#include<algorithm> #include<iostream> #include<cstring> #include<cstdio> //by NeighThorn #define u32 unsigned long long using namespace std; const int maxn=200000+5,maxm=7000000+5; int n,m,k,cnt,len,mod,a[maxn],ls[maxm],rs[maxm],sum[maxm],root[maxn]; u32 mp[maxn],Hash[maxn]; struct M{ int x,y,num[25]; u32 s; }q[maxn]; inline int find(u32 x){ int l=1,r=len,ans; while(l<=r){ int mid=(l+r)>>1; if(mp[mid]>=x) ans=mid,r=mid-1; else l=mid+1; } return ans; } inline void change(int l,int r,int x,int &y,int val){ y=++cnt;sum[y]=sum[x]+1; if(l==r) return; int mid=(l+r)>>1;ls[y]=ls[x];rs[y]=rs[x]; if(val<=mid) change(l,mid,ls[x],ls[y],val); else change(mid+1,r,rs[x],rs[y],val); } inline int query(int l,int r,int x,int y,int val){ if(l==r){ if(sum[y]-sum[x]>0) return 1; else return 0; } int mid=(l+r)>>1; if(val<=mid) return query(l,mid,ls[x],ls[y],val); else return query(mid+1,r,rs[x],rs[y],val); } signed main(void){ scanf("%d%d%d",&n,&m,&k);len=0;mod=n+1; for(int i=1;i<=n;i++) scanf("%d",&a[i]); for(int i=1;i<=m;i++){ scanf("%d%d",&q[i].x,&q[i].y); for(int j=1;j<=k;j++) scanf("%d",&q[i].num[j]); } for(int i=1;i<=m;i++){ q[i].s=0; for(int j=1;j<=k;j++) q[i].s=q[i].s*mod+1ULL*q[i].num[j]; mp[++len]=q[i].s; } for(int i=1,j=k;j<=n;i++,j++){ Hash[j]=0ULL; for(int t=i;t<=j;t++) Hash[j]=Hash[j]*mod+a[t]; mp[++len]=Hash[j]; } sort(mp+1,mp+len+1),len=unique(mp+1,mp+len+1)-mp-1; for(int i=k;i<=n;i++) change(1,len,root[i-1],root[i],find(Hash[i])); for(int i=1;i<=m;i++){ if(!query(1,len,root[q[i].x+k-2],root[q[i].y],find(q[i].s))) puts("Yes"); else puts("No"); } return 0; }
By NeighThorn