1. 程式人生 > >【NOI模擬】維護佇列

【NOI模擬】維護佇列

Description

 你小時候玩過彈珠嗎?
  小朋友A有一些彈珠,A喜歡把它們排成佇列,從左到右編號為1到N。為了整個佇列鮮豔美觀,小朋友想知道某一段連續彈珠中,不同顏色的彈珠有多少。當然,A有時候會依據個人喜好,替換佇列中某個彈珠的顏色。但是A還沒有學過程式設計,且覺得頭腦風暴太浪費腦力了,所以向你來尋求幫助。

Solution

Code

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define fo(i,a,b) for(i=a;i<=b;i++) #define fod(i,a,b) for(i=a;i>=b;i--) using namespace std; const int maxn=50007; struct node{ int l,r,x,p; }a[maxn]; struct nod{ int x,y,o; }d[maxn]; int i,j,k,l,t,n,m,ans,now,kuai[maxn],da,last[maxn],tot,num,r; bool bz[maxn]; int shu[1000007],b[maxn],ans1[maxn]; char
s[10]; bool cmp(node x,node y){ return kuai[x.l]<kuai[y.l]||kuai[x.l]==kuai[y.l]&&x.r<y.r||kuai[x.l]==kuai[y.l]&&x.r==y.r&&x.x<y.x; } void update(int x){ if(bz[x]){ shu[b[x]]--; if(!shu[b[x]])ans--; } else{ shu[b[x]]++; if
(shu[b[x]]==1)ans++; } bz[x]^=1; } void change(int x,int y){ if(bz[x]){ update(x);b[x]=y;update(x); } else b[x]=y; } int main(){ //freopen("fan.in","r",stdin); //freopen("fan.out","w",stdout); scanf("%d%d",&n,&m); da=500; fo(i,1,n)scanf("%d",&b[i]),kuai[i]=i/da,last[i]=b[i]; fo(i,1,m) { scanf("%s%d%d",s,&k,&l); if (s[0]=='Q')a[++tot].l=k,a[tot].r=l,a[tot].x=num,a[tot].p=tot; else d[++num].x=k,d[num].o=last[k],d[num].y=l,last[k]=l; } sort(a+1,a+1+tot,cmp); l=1; fo(i,1,tot){ if (now<a[i].x)fo(j,now+1,a[i].x)change(d[j].x,d[j].y); else fod(j,now,a[i].x+1)change(d[j].x,d[j].o); if (l<a[i].l)fo(j,l,a[i].l-1)update(j); else fo(j,a[i].l,l-1)update(j); if (r<a[i].r)fo(j,r+1,a[i].r)update(j); else fo(j,a[i].r+1,r)update(j); ans1[a[i].p]=ans;l=a[i].l;r=a[i].r;now=a[i].x; } fo(i,1,tot)printf("%d\n",ans1[i]); }