【BZOJ 2453|bzoj 2120】 2453: 维护队列 (分块+二分)
2453: 维护队列
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
1HINT
对于100%的数据,有1 ≤ N ≤ 10000, 1 ≤ M ≤ 10000,小朋友A不会修改超过1000次,所有颜色均用1到10^6的整数表示。
Source
【分析】
跟BZOJ 3343 差不多。
对序列求一个next,next[i]表示下一个和i同颜色的是谁(如果他是最后一个的这种颜色,那么next为正无穷)
问题转换成计算区间[l,r]里面next大于r的有多少个,单点修改。
转化成跟BZOJ 3343 一样的模型。
根号n分块,块内要排序。next这条链的删除和插入可以暴力枚举,因为数据范围很小。
时间复杂度是O(q*√n log(√n)+q*n)
1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 #include<iostream> 5 #include<algorithm> 6 #include<cmath> 7 using namespace std; 8 #define Maxn 10010 9 #define Maxd 1000010 10 11 int a[Maxn],pos[Maxn],ft[Maxn],rt[Maxn]; 12 int nt[Maxn],lt[Maxd],b[Maxn]; 13 int n; 14 15 bool cmp(int x,int y) {return x>y;} 16 17 void upd(int x) 18 { 19 for(int i=ft[x];i<=rt[x];i++) b[i]=nt[i]; 20 sort(b+ft[x],b+1+rt[x],cmp); 21 } 22 23 void change(int x,int y) 24 { 25 if(lt[a[x]]==x) 26 { 27 lt[a[x]]=nt[x]; 28 } 29 else 30 { 31 for(int i=lt[a[x]];i<=n;i=nt[i]) if(nt[i]==x) 32 { 33 nt[i]=nt[x]; 34 upd(pos[i]); 35 break; 36 } 37 } 38 if(x<lt[y]) 39 { 40 nt[x]=lt[y]; 41 lt[y]=x; 42 } 43 else 44 { 45 for(int i=lt[y];i<=n;i=nt[i]) if(nt[i]>x) 46 { 47 nt[x]=nt[i]; 48 nt[i]=x; 49 upd(pos[i]); 50 break; 51 } 52 } 53 upd(pos[x]); 54 a[x]=y; 55 } 56 57 int ffind(int x,int y) 58 { 59 int l=ft[x],r=rt[x]; 60 if(b[l]<y) return 0; 61 while(l<r) 62 { 63 int mid=(l+r+1)>>1; 64 if(b[mid]>y) l=mid; 65 else r=mid-1; 66 } 67 return l-ft[x]+1; 68 } 69 70 int query(int x,int y) 71 { 72 int ans=0; 73 if(pos[x]==pos[y]) 74 { 75 for(int i=x;i<=y;i++) if(nt[i]>y) ans++; 76 } 77 else 78 { 79 for(int i=x;i<=rt[pos[x]];i++) if(nt[i]>y) ans++; 80 for(int i=ft[pos[y]];i<=y;i++) if(nt[i]>y) ans++; 81 for(int i=pos[x]+1;i<pos[y];i++) ans+=ffind(i,y); 82 } 83 return ans; 84 } 85 86 int main() 87 { 88 int m,sq; 89 scanf("%d%d",&n,&m); 90 sq=(int)ceil(sqrt((double)n)); 91 for(int i=1;i<=n;i++) scanf("%d",&a[i]); 92 for(int i=1;i<=Maxd;i++) lt[i]=n+1; 93 for(int i=n;i>=1;i--) nt[i]=lt[a[i]],lt[a[i]]=i; 94 for(int i=1;i<=n;i++) pos[i]=(i-1)/sq+1; 95 for(int i=1;i<n;i++) if(pos[i]!=pos[i+1]) ft[pos[i+1]]=i+1,rt[pos[i]]=i; 96 ft[1]=1;rt[pos[n]]=n; 97 for(int i=1;i<=n;i++) b[i]=nt[i]; 98 for(int i=1;i<=pos[n];i++) sort(b+ft[i],b+1+rt[i],cmp); 99 100 for(int i=1;i<=m;i++) 101 { 102 char s[10]; 103 int x,y; 104 scanf("%s%d%d",s,&x,&y); 105 if(s[0]=='R') 106 { 107 change(x,y); 108 } 109 else 110 { 111 printf("%d\n",query(x,y)); 112 } 113 } 114 return 0; 115 }
2016-12-12 13:52:29