bzoj4722 由乃
Description
由于一周目的由乃穿越到了三周目,并带来了巨大的影响,改变了三周目所有未来日记所有者的命运所以三周目的神Deus准备不利用未来日记来决定把神的位置交给谁Deus特别崇拜某知名社会主义国家领导人,因为他的寿命比神还长,所以他想钦定下一个卡密,而不通过选举他决定钦定三周目的由乃成为卡密,去和一周目的雪辉重逢(终于做了一件好事了)但是,既然是钦定,那么肯定还是要做做样子的,以防某些来自香港的记者造个大新闻,导致被批判一番所以Deus决定,出一道OI题来考察由乃有没有当神的能力如果你没有看过这个番,以上内容可以无视
给一个长为n的序列a,每个数在0到v - 1之间,有m次操作。
操作1:每次询问一个区间中是否可以选出两个下标的集合X,Y,满足:
1.X和Y没有交集
2.设集合X中有一个元素是i,则其对集合X的贡献是a[i] + 1,要求集合X的元素的总贡献和集合Y的元素的总贡献
相等如果可以选出这两个集合,输出 Yuno否则输出 Yuki
操作2:修改一个区间l,r之间的数,使得所有l <= i <= r,a[i] = a[i] * a[i] * a[i] % v ,即区间立方
如果你没有看过这个番,或者你已经是国家队队员,以下内容可以无视
可以去和雪辉重逢,由乃肯定非常高兴然而可爱的由乃虽然很机智但是并不会OI呀,特别不会数据结构这种神奇的东西(会数据结构和成为卡密有什么关系吗233333)所以她请您——未来的国家队队员来帮助她啦
Input
第一行三个数n , m , v,意义如题所述
之后一行n个数,表示序列a
之后m行每行三个数opt , l , r,表示操作类型是1还是2,操作的区间是[l , r]
Output
m行,每行一个字符串 Yuno 或者 Yuki 表示能否选出这两个集合
Sample Input
20 20 152
3 26 133 54 79 81 72 109 66 91 82 100 35 23 104 17 51 114 12 58
2 1 17
2 6 12
1 1 12
2 3 5
2 11 11
2 7 19
2 6 15
1 5 12
1 1 9
1 10 19
2 3 19
2 6 20
2 1 13
2 1 15
2 1 9
1 1 1
2 1 7
2 7 19
2 6 19
2 3 6
3 26 133 54 79 81 72 109 66 91 82 100 35 23 104 17 51 114 12 58
2 1 17
2 6 12
1 1 12
2 3 5
2 11 11
2 7 19
2 6 15
1 5 12
1 1 9
1 10 19
2 3 19
2 6 20
2 1 13
2 1 15
2 1 9
1 1 1
2 1 7
2 7 19
2 6 19
2 3 6
Sample Output
Yuno
Yuno
Yuno
Yuno
Yuki
Yuno
Yuno
Yuno
Yuki
HINT
总算在bzoj上出题了呀
这下可以安心退役了~
总共有10组数据
对于100%的数据,n , m <= 100000 , v <= 1000,数据没有梯度
正解:线段树+倍增+搜索。
首先这题有一个神奇的性质,就是当询问区间长度大于$13$的时候一定有合法解,因为$2^{14}>14*1000$。
然后我们判断一下,如果区间长度$\leq13$,那么我们就可以写$meet \ in \ the \ middle$,做到单次询问$O(3^{7})$。
再看修改怎么搞,因为$v<1000$,所以我们可以存下$x$的三次方是什么,进一步,可以存下$x$的$2^{k}$次三次方是什么,那么我们直接写一个倍增就行了。
1 #include <bits/stdc++.h> 2 #define il inline 3 #define RG register 4 #define ll long long 5 #define ls (x<<1) 6 #define rs (x<<1|1) 7 #define N (300010) 8 #define M (50010) 9 10 using namespace std; 11 12 int fa[21][N],sum[N<<2],tag[N<<2],vis[N],st[N],f[N],n,m,v,fg,top; 13 14 il int gi(){ 15 RG int x=0,q=1; RG char ch=getchar(); 16 while ((ch<'0' || ch>'9') && ch!='-') ch=getchar(); 17 if (ch=='-') q=-1,ch=getchar(); 18 while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar(); 19 return q*x; 20 } 21 22 il void pushdown(RG int x){ 23 tag[ls]+=tag[x],tag[rs]+=tag[x],tag[x]=0; return; 24 } 25 26 il void build(RG int x,RG int l,RG int r){ 27 if (l==r){ sum[x]=gi(); return; } RG int mid=(l+r)>>1; 28 build(ls,l,mid),build(rs,mid+1,r); return; 29 } 30 31 il void update(RG int x,RG int l,RG int r,RG int xl,RG int xr){ 32 if (xl<=l && r<=xr){ ++tag[x]; return; } 33 if (tag[x]) pushdown(x); RG int mid=(l+r)>>1; 34 if (xr<=mid) update(ls,l,mid,xl,xr); 35 else if (xl>mid) update(rs,mid+1,r,xl,xr); 36 else update(ls,l,mid,xl,mid),update(rs,mid+1,r,mid+1,xr); 37 return; 38 } 39 40 il int query(RG int x){ 41 sum[x]%=v; 42 for (RG int j=20;j>=0;--j) 43 if (tag[x]>=(1<<j)) tag[x]-=1<<j,sum[x]=fa[j][sum[x]]; 44 return sum[x]; 45 } 46 47 il void find(RG int x,RG int l,RG int r,RG int xl,RG int xr,RG int p){ 48 if (l==r){ f[r-p+1]=query(x); return; } 49 if (tag[x]) pushdown(x); RG int mid=(l+r)>>1; 50 if (xr<=mid) find(ls,l,mid,xl,xr,p); 51 else if (xl>mid) find(rs,mid+1,r,xl,xr,p); 52 else find(ls,l,mid,xl,mid,p),find(rs,mid+1,r,mid+1,xr,p); 53 } 54 55 il void dfs1(RG int x,RG int lim,RG int sz,RG int tot){ 56 if (x>lim){ 57 if (!sz) return; if (!tot){ fg=1; return; } 58 vis[tot+M]=1,st[++top]=tot; return; 59 } 60 dfs1(x+1,lim,sz+1,tot-f[x]-1),dfs1(x+1,lim,sz,tot); 61 dfs1(x+1,lim,sz+1,tot+f[x]+1); return; 62 } 63 64 il void dfs2(RG int x,RG int lim,RG int sz,RG int tot){ 65 if (x>lim){ 66 if (!sz) return; if (!tot) fg=1; 67 if (vis[M-tot]) fg=1; return; 68 } 69 dfs2(x+1,lim,sz+1,tot-f[x]-1),dfs2(x+1,lim,sz,tot); 70 dfs2(x+1,lim,sz+1,tot+f[x]+1); return; 71 } 72 73 il int check(RG int len){ 74 if (len>13) return 1; fg=top=0,dfs1(1,len/2,0,0); 75 if (fg){ for (RG int i=1;i<=top;++i) vis[st[i]+M]=0; return 1; } 76 dfs2(len/2+1,len,0,0); for (RG int i=1;i<=top;++i) vis[st[i]+M]=0; return fg; 77 } 78 79 int main(){ 80 #ifndef ONLINE_JUDGE 81 freopen("yuno.in","r",stdin); 82 freopen("yuno.out","w",stdout); 83 #endif 84 n=gi(),m=gi(),v=gi(),build(1,1,n); 85 for (RG int i=1;i<v;++i) fa[0][i]=1LL*i*i*i%v; 86 for (RG int j=1;j<=20;++j) 87 for (RG int i=1;i<v;++i) fa[j][i]=fa[j-1][fa[j-1][i]]; 88 while (m--){ 89 RG int op=gi(),l=gi(),r=gi(); 90 if (op==1){ 91 if (r-l+1<=13) find(1,1,n,l,r,l); 92 puts(check(r-l+1) ? "Yuno" : "Yuki"); 93 } else update(1,1,n,l,r); 94 } 95 return 0; 96 }