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 }
时间: 2024-08-24 22:22:49

BZOJ2821作诗【分块】的相关文章

刷题总结——分块算法(bzoj2821作诗)

题目: Description 神犇SJY虐完HEOI之后给傻×LYD出了一题:SHY是T国的公主,平时的一大爱好是作诗.由于时间紧迫,SHY作完诗 之后还要虐OI,于是SHY找来一篇长度为N的文章,阅读M次,每次只阅读其中连续的一段[l,r],从这一段中选出一 些汉字构成诗.因为SHY喜欢对偶,所以SHY规定最后选出的每个汉字都必须在[l,r]里出现了正偶数次.而且SHY认 为选出的汉字的种类数(两个一样的汉字称为同一种)越多越好(为了拿到更多的素材!).于是SHY请LYD安排选 法.LYD这

【分块】bzoj2821 作诗(Poetize)

分块,预处理出: ①第i块到第j块之间的偶数值的种类数. ②在前i块中,每个值出现的次数.(前缀和)(差分) 每次询问时,对于不在整块中的元素,进行暴力转移. 注意:减少memset的使用,千万不要写100000个memset,否则会TLE,宁愿每次询问之后O(sqrt(n))地一个个减掉那个记录每个值出现次数的临时数组. Code: 1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 #incl

bzoj2821作诗

http://www.lydsy.com/JudgeOnline/problem.php?id=2821 分块 我们把数列分成$\sqrt{N}$块 记$f[i][j]$表示第i块到第j块的答案,这个可以在$O(N\sqrt{N})$内得到. 记$g[i][j]$第1到第i块中数字j出现了多少次,这个我们可以先求出第i块中数字j出现了多少次,然后求前缀和即可,这个可以在$O(C\sqrt{N})$内得到. 对于询问区间[l,r]我们可以从f数组中快速求出中间连续的完整的块答案. 对于剩余部分,我

bzoj2821 作诗(Poetize)

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=2821 [题解] 今天看了黄学长的分块专项 感觉十分科学就来刚刚分块了. 这题我们套用区间众数的办法.令f[i,j]表示i块到j块的答案,g[i,j]表示1...i块,数字为j的有多少个. 然后我们大区间个数可以直接调用,两边暴力做. 注意清零问题不能出现复杂度退化. 有两种办法,一个是把所有即将出现的数的位置都清空或赋值,一种是排序后,找到第一个的时候赋值,后面累加. 后面那个是popoq

P4135 作诗——分块

题目:https://www.luogu.org/problemnew/show/P4135 分块大法: 块之间记录答案,每一块记录次数前缀和: 注意每次把桶中需要用到位置赋值就好了: 为什么加了特判会 T 一个点? 代码如下: #include<iostream> #include<cstdio> #include<cstring> #include<cmath> using namespace std; int const maxn=1e5+5; int

【BZOJ2821】作诗(Poetize) 分块

Description 神犇SJY虐完HEOI之后给傻×LYD出了一题:SHY是T国的公主,平时的一大爱好是作诗.由于时间紧迫,SHY作完诗之后还要虐OI,于是SHY找来一篇长度为N的文章,阅读M次,每次只阅读其中连续的一段[l,r],从这一段中选出一些汉字构成诗.因为SHY喜欢对偶,所以SHY规定最后选出的每个汉字都必须在[l,r]里出现了正偶数次.而且SHY认为选出的汉字的种类数(两个一样的汉字称为同一种)越多越好(为了拿到更多的素材!).于是SHY请LYD安排选法.LYD这种傻×当然不会了

BZOJ 2821: 作诗(Poetize)( 分块 )

分块,分成N^0.5块.O(N^1.5)预处理出sm[i][j]表示前i块中j的出现次数, ans[i][j]表示第i~j块的答案. 然后就可以O(N^0.5)回答询问了.总复杂度O((N+Q)N^0.5) ----------------------------------------------------------------------------------------- #include<cstdio> #include<algorithm> #include<

巴蜀4384 -- 【模拟试题】作诗(Poetize)

Description 神犇SJY虐完HEOI之后给傻×LYD出了一题:SHY是T国的公主,平时的一大爱好是作诗.由于时间紧迫,SHY作完诗之后还要虐OI,于是SHY找来一篇长度为N的文章,阅读M次,每次只阅读其中连续的一段[l,r],从这一段中选出一些汉字构成诗.因为SHY喜欢对偶,所以SHY规定最后选出的每个汉字都必须在[l,r]里出现了正偶数次.而且SHY认为选出的汉字的种类数(两个一样的汉字称为同一种)越多越好(为了拿到更多的素材!).于是SHY请LYD安排选法.LYD这种傻×当然不会了

[Luogu 4135] 作诗

Description 神犇SJY虐完HEOI之后给傻×LYD出了一题: SHY是T国的公主,平时的一大爱好是作诗. 由于时间紧迫,SHY作完诗之后还要虐OI,于是SHY找来一篇长度为N的文章,阅读M次,每次只阅读其中连续的一段[l,r],从这一段中选出一些汉字构成诗.因为SHY喜欢对偶,所以SHY规定最后选出的每个汉字都必须在[l,r]里出现了正偶数次.而且SHY认为选出的汉字的种类数(两个一样的汉字称为同一种)越多越好(为了拿到更多的素材!).于是SHY请LYD安排选法. LYD这种傻×当然