Jeff and Removing Periods CodeForces - 351D (莫队)

    xiaoxiao2022-07-07  183

    题目:点击此处

    题意:给你n个数,q个询问,问每个区间的数最少需要几步可以删除完

    删除的是一个等差序列

    由于第一次删除之后,剩下的数字随机排列,所以,只要第一次删除可以把一种数字全部删除,剩下的步数就是数字种类数

    总步数即为  总的种类数

     如果一次删不完一种数,那么答案就是总的种类数+1

    判断是否是等差序列需要预处理  两个数组  fl[N],fr[N];

    fl[i]表示i位置往左第一个构不成等差序列的位置

    fr[i]同理;

     

    #include <cstdio> #include <cmath> #include <cstring> #include <string> #include <algorithm> #include <queue> #include <map> #include <set> #include <vector> #include <iostream> using namespace std; const int N=100005; struct node { int x,y,p; }q[N]; bool cmp(node a,node b) { if (a.x/block!=b.x/block) return a.x/block<b.x/block; return a.y<b.y; } int aa[N]; int bak[N]; int pre[N]; int last[N]; int fl[N],fr[N]; int cnt[N]; int dengcha=0; int kind=0; int ans[N]; int L,R,block=sqrt(N); void add1(int x) { if(cnt[aa[x]]==0) { dengcha++; kind++; } else { if(fr[x]<=R&&fr[bak[x]]>R) dengcha--; } cnt[aa[x]]++; } void remov1e(int x) { if(cnt[aa[x]]==1) { dengcha--; kind--; } else { if(fr[x]<=R&&fr[bak[x]]>R) dengcha++; } cnt[aa[x]]--; } void add2(int x,int l) { if(cnt[aa[x]]==0) { dengcha++; kind++; } else { if(fl[x]>=l&&fl[pre[x]]<l) dengcha--; } cnt[aa[x]]++; } void remov2e(int x,int l) { if(cnt[aa[x]]==1) { dengcha--; kind--; } else { if(fl[x]>=l&&fl[pre[x]]<l) dengcha++; } cnt[aa[x]]--; } void query(int x,int y,int flag) { if (flag) { while(L>=x) { add1(L-1); L--; } while(L<x) { remov1e(L); L++; } while(R>y) { remov2e(R,x); R--; } while(R<y) { add2(R+1,x); R++; } } else { for (int i=x;i<=y;i++) { if(cnt[aa[i]]==0) { dengcha++; kind++; } else { if (fl[i]>=x&&fl[pre[i]]<x) dengcha--;//fl[i]>=x 指 i位置往左第一个构不成等差序列的位置在区间内, fl[pre[i]]<x 指 pre[i]位置往左第一个构不成等差序列的位置不在区间内,(防止重复计算) } cnt[aa[i]]++; } L=x,R=y; } } void init() { int i; kind = 0; for (i=1; i<=m; i++) //预处理 { scanf("%d",&aa[i]); pre[i]=last[aa[i]]; last[aa[i]]=i; if (pre[pre[i]]-pre[i]==pre[i]-i||pre[i]==0) fl[i]=fl[pre[i]]; else fl[i]=pre[pre[i]]; } fill(last,m+last,m+1); for (i=m; i>=1; i--) { bak[i]=last[aa[i]]; last[aa[i]]=i; if (bak[bak[i]]-bak[i]==bak[i]-i||bak[i]==m+1) fr[i]=fr[bak[i]]; else fr[i]=bak[bak[i]]; } } int main() { int m,i,j,qq,; cin>>m; init(); scanf("%d",&qq); for (i=0;i<qq; i++) { scanf("%d%d",&q[i].x,&q[i].y); q[i].l=q[i].x/block_size; q[i].p=i; } sort(q,q+qq,cmp); for (i=0;i<qq;i++) { query(q[i].x,q[i].y, i); ans[q[i].p]=kind+1; if (dengcha>0) ans[q[i].p]--; } for (i=0;i<qq;i++) printf("%d\n",ans[i]); return 0; }

     

    最新回复(0)