2453: 维护队列
Time Limit: 10 Sec Memory Limit: 128 MB
Submit: 952 Solved: 432
[Submit][Status][Discuss]
Description
你小时候玩过弹珠吗?
小朋友A有一些弹珠,A喜欢把它们排成队列,从左到右编号为1到N。为了整个队列鲜艳美观,小朋友想知道某一段连续弹珠中,不同颜色的弹珠有多少。当然,A有时候会依据个人喜好,替换队列中某个弹珠的颜色。但是A还没有学过编程,且觉得头脑风暴太浪费脑力了,所以向你来寻求帮助。
Input
输入文件第一行包含两个整数N和M。
第二行N个整数,表示初始队列中弹珠的颜色。
接下来M行,每行的形式为“Q L R”或“R x c”,“Q L R”表示A想知道从队列第L个弹珠到第R个弹珠中,一共有多少不同颜色的弹珠,“R x c”表示A把x位置上的弹珠换成了c颜色。
Output
对于每个Q操作,输出一行表示询问结果。
Sample Input
2 3
1 2
Q 1 2
R 1 2
Q 1 2
Sample Output
2
1
HINT
对于100%的数据,有1 ≤ N ≤ 10000, 1 ≤ M ≤ 10000,小朋友A不会修改超过1000次,所有颜色均用1到10^6的整数表示。
Source
2011福建集训
把询问和修改分开排序,修改按时间排,询问以左端点所在块为第一关键字,右端点所在块为第二关键字,时间为第三关键字排序。
维护左右时间三个指针,不断修改还原。
块大小为$n^{\frac{2}{3}}$。
左指针每个询问走$n^{\frac{2}{3}}$。
右指针同理,不过要多上每次总从左走到右的复杂度,总共$n\times n^{\frac{2}{3}}+n\times n^{\frac{1}{3}}$。
时间指针每次左右端点所在块变化重新开始走,一共$n^{\frac{2}{3}}$个不同的左右块匹配数,复杂度$n\times n^{\frac{2}{3}}$.
好像块开100比较快。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #define d 100 6 #define N 10005 7 using namespace std; 8 int n,m; 9 int c[N]; 10 struct node 11 { 12 int l,r,t,pr; 13 node(){l=r=t=0;} 14 }q[N],g[N]; 15 int cnt1,cnt2; 16 bool cmp1(const node &aa,const node &bb) 17 { 18 return aa.t<bb.t; 19 } 20 int be1[N],be2[N]; 21 bool cmp2(const node &aa,const node &bb) 22 { 23 if(be1[aa.l]==be1[bb.l]) 24 { 25 if(be2[aa.r]==be2[bb.r])return aa.t<bb.t; 26 return aa.r<bb.r; 27 } 28 return aa.l<bb.l; 29 } 30 int ans[N]; 31 int now[N*100],cnt; 32 void solve() 33 { 34 int p1,p2,p; 35 memset(now,0,sizeof(now)); 36 now[c[1]]=1;cnt=1;g[cnt1+1].t=10005; 37 p=p1=1; 38 p2=0; 39 for(int i=1;i<=cnt2;i++) 40 { 41 while(g[p2+1].t<q[i].t) 42 { 43 p2++; 44 int tmp=c[g[p2].l]; 45 g[p2].pr=tmp; 46 c[g[p2].l]=g[p2].r; 47 if(g[p2].l<=p&&g[p2].l>=p1) 48 { 49 now[tmp]--; 50 if(!now[tmp])cnt--; 51 now[g[p2].r]++; 52 if(now[g[p2].r]==1)cnt++; 53 } 54 } 55 while(g[p2].t>q[i].t) 56 { 57 58 c[g[p2].l]=g[p2].pr; 59 if(g[p2].l<=p&&g[p2].l>=p1) 60 { 61 now[g[p2].r]--; 62 if(!now[g[p2].r])cnt--; 63 now[g[p2].pr]++; 64 if(now[g[p2].pr]==1)cnt++; 65 } 66 p2--; 67 } 68 while(p<q[i].r) 69 { 70 p++;now[c[p]]++; 71 if(now[c[p]]==1)cnt++; 72 } 73 while(p>q[i].r) 74 { 75 now[c[p]]--;if(!now[c[p]])cnt--; 76 p--; 77 } 78 while(p1<q[i].l) 79 { 80 now[c[p1]]--;if(!now[c[p1]])cnt--; 81 p1++; 82 } 83 while(p1>q[i].l) 84 { 85 p1--;now[c[p1]]++; 86 if(now[c[p1]]==1)cnt++; 87 } 88 ans[q[i].t]=cnt; 89 } 90 } 91 int main() 92 { 93 scanf("%d%d",&n,&m); 94 for(int i=1;i<=n;i++)scanf("%d",&c[i]); 95 for(int i=1;i<=n;i++) 96 { 97 be1[i]=be2[i]=(i-1)/d+1; 98 } 99 memset(ans,-1,sizeof(ans)); 100 char s[2]; 101 for(int i=1;i<=m;i++) 102 { 103 scanf("%s",s); 104 if(s[0]==‘R‘) 105 { 106 cnt1++; 107 scanf("%d%d",&g[cnt1].l,&g[cnt1].r); 108 g[cnt1].t=i; 109 } 110 else 111 { 112 cnt2++; 113 scanf("%d%d",&q[cnt2].l,&q[cnt2].r); 114 q[cnt2].t=i; 115 } 116 } 117 sort(q+1,q+cnt2+1,cmp2); 118 sort(g+1,g+cnt1+1,cmp1); 119 solve(); 120 for(int i=1;i<=m;i++) 121 { 122 if(ans[i]!=-1)printf("%d\n",ans[i]); 123 } 124 return 0; 125 }