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

Sample Output

Yuno
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 }

 

posted @ 2017-09-27 20:01  wfj_2048  阅读(238)  评论(0编辑  收藏  举报