首页 > 代码库 > BZOJ2821作诗【分块】
BZOJ2821作诗【分块】
Description
神犇SJY虐完HEOI之后给傻×LYD出了一题:SHY是T国的公主,平时的一大爱好是作诗。由于时间紧迫,SHY作完诗之后还要虐OI,于是SHY找来一篇长度为N的文章,阅读M次,每次只阅读其中连续的一段[l,r],从这一段中选出一些汉字构成诗。因为SHY喜欢对偶,所以SHY规定最后选出的每个汉字都必须在[l,r]里出现了正偶数次。而且SHY认为选出的汉字的种类数(两个一样的汉字称为同一种)越多越好(为了拿到更多的素材!)。于是SHY请LYD安排选法。LYD这种傻×当然不会了,于是向你请教……问题简述:N个数,M组询问,每次问[l,r]中有多少个数出现正偶数次。
Input
输入第一行三个整数n、c以及m。表示文章字数、汉字的种类数、要选择M次。第二行有n个整数,每个数Ai在[1, c
]间,代表一个编码为Ai的汉字。接下来m行每行两个整数l和r,设上一个询问的答案为ans(第一个询问时ans=0),
令L=(l+ans)mod n+1, R=(r+ans)mod n+1,若L>R,交换L和R,则本次询问为[L,R]。
Output
输出共m行,每行一个整数,第i个数表示SHY第i次能选出的汉字的最多种类数。
Sample Input
5 3 5
1 2 2 3 1
0 4
1 2
2 2
2 3
3 5
Sample Output
2
0
0
0
1
HINT
对于100%的数据,1<=n,c,m<=10^5
有趣的分块...
分成sqrt(n)个块以后处理处i到j个块的答案,将原序列排序,这样整块的两边的元素可以在整块区间中查找相同元素检测对答案的影响.
要注意计算影响时什么时候+、-,要判断原来有没有。。。无力吐槽
1 #include<cstdio>
2 #include<cstring>
3 #include<algorithm>
4 #include<cmath>
5 #include<iostream>
6 using namespace std;
7 const int N=100005;
8 const int M=350;
9 struct node{
10 int a,p;
11 }e[N];
12 int pos[N],d[N],S,map[M][M],le[M*3],ans=0,a,b,size=0;
13 int num[N],x[N],y[N];
14 inline bool cmp(node x,node y)
15 {
16 if(x.a!=y.a) return x.a<y.a;
17 return x.p<y.p;
18 }
19 inline int find(int u,int l,int r)
20 {
21 int cnt=0;
22 for(int i=x[u];i<=y[u];i++)
23 {
24 if(l<=e[i].p&&e[i].p<=r) cnt++;
25 if(e[i].p>r) break;
26 }
27 return cnt;
28 }
29 inline void get_ans(int l,int r)
30 {
31 sort(le+1,le+size+1);
32 int cnt=0,k;
33 for(int i=1;i<=size;i++)
34 {
35 cnt++;
36 if(le[i]!=le[i+1])
37 {
38 k=find(le[i],l,r);
39 if(k%2==0&&k&&cnt%2==1) ans--;
40 else if(k%2==1&&cnt%2==1) ans++;
41 else if(k==0&&cnt%2==0) ans++;
42 cnt=0;
43 }
44 }
45 }
46 int main()
47 {
48 int n,m,c,t,cnt,l,r;
49 int k=0;
50 scanf("%d%d%d",&n,&c,&m);
51 S=(int)sqrt(n);
52 for(int i=1;i<=n;i++)
53 {
54 scanf("%d",&d[i]);
55 e[i].a=d[i];
56 e[i].p=i;
57 pos[i]=(i-1)/S+1;
58 }
59 t=pos[n];
60 sort(e+1,e+n+1,cmp);
61 x[e[1].a]=1;
62 for(int i=1;i<=n;i++) if(e[i].a!=e[i+1].a)
63 {
64 y[e[i].a]=i;
65 x[e[i+1].a]=i+1;
66 }
67 for(int i=1;i<=t;i++)
68 {
69 memset(num,0,sizeof(num));
70 cnt=0;
71 for(int j=(i-1)*S+1;j<=n;j++)
72 {
73 num[d[j]]++;
74 if(num[d[j]]%2==0) cnt++;
75 else if(num[d[j]]>1&&num[d[j]]%2==1) cnt--;
76 if(pos[j]!=pos[j+1]) map[i][pos[j]]=cnt;
77 }
78 }
79 while(m--)
80 {
81 scanf("%d%d",&l,&r);
82 l=(l+ans)%n+1;
83 r=(r+ans)%n+1;
84 if(l>r) swap(l,r);
85 if(pos[l]==pos[r]||pos[l]+1==pos[r])
86 {
87 memset(num,0,sizeof(num));
88 ans=0;
89 for(int i=l;i<=r;i++)
90 {
91 num[d[i]]++;
92 if(num[d[i]]%2==0) ans++;
93 else if(num[d[i]]>1&&num[d[i]]%2==1) ans--;
94 }
95 printf("%d\n",ans);
96 continue;
97 }
98 memset(le,0,sizeof(le));
99 size=0;
100 if(pos[l]==pos[l-1])
101 {
102 a=pos[l]+1;
103 while(pos[l]==pos[l-1]&&l<=n) le[++size]=d[l],l++;
104 }
105 else a=pos[l];
106 if(pos[r]==pos[r+1])
107 {
108 b=pos[r]-1;
109 while(pos[r]==pos[r+1]&&r>0) le[++size]=d[r],r--;
110 }
111 else b=pos[r];
112 ans=map[a][b];
113 get_ans(l,r);
114 printf("%d\n",ans);
115 }
116 return 0;
117 }
BZOJ2821作诗【分块】
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。