P4135 作诗

题目

  • 很容易想到分块。

  • 类似于区间众数的操作。

  • 首先预处理出两个数组:

    1. f 二维数组表示两个块为左右边界的序列的答案。

    2. s 二维数组处理出从第一个块到某一个块之间每

        个数出现的次数。

  • 对于询问其实和预处理 f 数组的做法差不多。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int l,r;
 4 int n,m,c,block,sm;
 5 int val[100050];
 6 int f[350][350];
 7 int col[100050];
 8 int L[350],R[350];
 9 int s[350][100050];
10 int t[100050],ans;
11 int T[100050],TOP;
12 void calc()
13 {
14     ans=f[col[l]+1][col[r]-1];    TOP=0;
15     if(col[l]!=col[r])
16     {
17         for(int i=l;i<=R[col[l]];++i)
18             T[++TOP]=val[i];
19         for(int i=r;i>=L[col[r]];--i)
20             T[++TOP]=val[i];
21         for(int i=1;i<=TOP;++i)
22             t[T[i]]=s[col[r]-1][T[i]]-s[col[l]][T[i]];
23     }
24     else
25     {
26         for(int i=l;i<=r;++i)
27             T[++TOP]=val[i];
28         for(int i=1;i<=TOP;++i)
29             t[T[i]]=0;
30     }
31 }
32 int main()
33 {
34     scanf("%d%d%d",&n,&c,&m);
35     block=sqrt(n);sm=n/block+1;
36     for(int i=1;i<=sm;++i)
37         L[i]=n,R[i]=1;
38     for(int i=1;i<=n;++i)
39     {
40         col[i]=i/block+1;
41         scanf("%d",&val[i]);
42         ++s[col[i]][val[i]];
43         L[col[i]]=min(L[col[i]],i);
44         R[col[i]]=max(R[col[i]],i);
45     }
46     for(int i=1;i<=sm;++i)
47         for(int j=1;j<=c;++j)
48             s[i][j]+=s[i-1][j];
49     for(int i=1;i<=sm;++i)
50     {
51         for(int j=L[i];j<=n;++j)
52         {
53             ++t[val[j]];
54             if(t[val[j]]==1)
55                 ;
56             else if(t[val[j]]&1)
57                 --ans;
58             else    
59                 ++ans;
60             if(j==R[col[j]])
61                 f[i][col[j]]=ans;
62         }
63         memset(t,0,sizeof(t));
64         ans=0;
65     }
66     while(m--)
67     {
68         scanf("%d%d",&l,&r);
69         l=(l+ans)%n+1;
70         r=(r+ans)%n+1;
71         if(l>r)
72             swap(l,r);
73         calc();
74         for(int i=1;i<=TOP;++i)
75         {
76             ++t[T[i]];
77             if(t[T[i]]==1)
78                 ;
79             else if(t[T[i]]&1)
80                 --ans;
81             else    
82                 ++ans;
83         }
84         printf("%d\n",ans);
85     }
86     return 0;
87 }
View Code
posted @ 2019-02-24 21:39  Hevix  阅读(179)  评论(0编辑  收藏  举报