CF 813E Army Creation 分块|主席树

一、分块

核心就是找到分块要维护的东西。想象一列数字中,我们取出其中相同的一组,我们要在给定范围内取不超过k个,如果暴力从左往右判断然后记录个数,很不现实吧。那我们就开个数组记录这个数在此中的位置+k个后会不会超过这一组的个数,但之后统计的关键不是“从左往右”。如果碰到的数+k后还在区间内,我们不做记录,因为这样限制条件就会很多,分块询问时中间的块也不好问,很容易出错(但说不定可以写)。我们可以转换思路,专找+k后大于边界的,这说明我们拿上它个数也不会超过k,这样ans++;之后分块,两边一个一个找,中间用二分找到大于边界的,直接加,所以前面要sort预处理。

//写得乱七八糟的题解,可能只有我自己才看得懂~~

 1 #include<bits/stdc++.h>
 2 #include<iostream>
 3 #include<stack>
 4 #include<algorithm>
 5 #include<cstdio>
 6 #include<cmath>
 7 #include<cstring>
 8 #define mem(a) memset(a,0,sizeof(a))
 9 #define ll long long
10 #define mp make_pair
11 #define pb push_back
12 #define inf 0x3f3f3f3f
13 using namespace std;
14 const int N=1e5+5;
15 int n,blo,num,belong[N],l[N],r[N],d[N],a[N],b[N],mx=0,k;
16 int nx[N];
17 vector<int>cnt[N];
18 void build()
19 {
20     blo=sqrt(n);
21     num=n/blo;
22     if(n%blo) num++;
23     for(int i=1;i<=n;i++)
24      {
25          belong[i]=((i-1)/blo)+1;
26          b[i]=nx[i];
27      }
28     for(int i=1;i<=num;i++)
29     {
30         l[i]=(i-1)*blo+1;
31         r[i]=i*blo;
32     }
33     r[num]=n;
34     for(int i=1;i<=num;i++)
35         sort(b+l[i],b+r[i]+1);
36 }
37 int query(int x,int y)
38 {
39    int ans=0;
40    for(int i=x;i<=min(r[belong[x]],y);i++)
41           if(nx[i]>y) ans++;
42    if(belong[x]!=belong[y])
43    {
44        for(int i=l[belong[y]];i<=y;i++)
45           if(nx[i]>y) ans++;
46        for(int i=belong[x]+1;i<=belong[y]-1;i++)
47        {
48            int j=b+r[i]+1-upper_bound(b+l[i],b+r[i]+1,y);
49            ans+=j;
50        }
51    }
52     return ans;
53 }
54 int main()
55 {
56      scanf("%d%d",&n,&k);
57      for(int i=1;i<=n;i++)
58      {
59           scanf("%d\n",&a[i]);
60           mx=max(mx,a[i]);
61      }
62      for(int i=1;i<=n;i++)
63         cnt[a[i]].pb(i);
64      for(int i=1;i<N;i++)
65      {
66          for(int j=0;j<cnt[i].size();j++)
67          {
68              if(j+k>=cnt[i].size())
69                 nx[cnt[i][j]]=N;
70              else
71                 nx[cnt[i][j]]=cnt[i][j+k];
72          }
73      }
74      build();
75      int last=0,m;
76      scanf("%d",&m);
77      while(m--)
78      {
79          int ans=0;
80          int L,R;
81          scanf("%d%d",&L,&R);
82          L=(L+last)%n+1;
83          R=(R+last)%n+1;
84          if(L>R)swap(L,R);
85          if(R-L+1<=k) ans=R-L+1;
86          else  ans=query(L,R);
87          printf("%d\n",ans);
88          last=ans;
89      }
90      build();
91 
92 }
<( ̄︶ ̄)↗[GO!]

猜你喜欢

转载自www.cnblogs.com/XXrll/p/11226689.html