莫队算法
分块大法吼
这题乍一看跟HH的项链很像啊……只是多了一个修改操作……然而我就不会做了
分块来搞吧!像糖果公园那样= =按左端点所在块为第一关键字,右端点所在块为第二关键字,修改时间为第三关键字……
然后暴力搞呗……
照着糖果公园的代码yy了半天终于是yy出来了……然而跪了……
RE & TLE:我是傻逼!c1和c2的声明跟cmd[5]放在一起了!应该是整型声明成char了!
Orz lct1999 ,编译时加 -Wall 就会提醒这些傻逼错误……新技能get√
1 /************************************************************** 2 Problem: 2120 3 User: Tunix 4 Language: C++ 5 Result: Accepted 6 Time:536 ms 7 Memory:5636 kb 8 ****************************************************************/ 9 10 //BZOJ 2120 11 #include<cstdio> 12 #include<cmath> 13 #include<cstring> 14 #include<cstdlib> 15 #include<iostream> 16 #include<algorithm> 17 #define rep(i,n) for(int i=0;i<n;++i) 18 #define F(i,j,n) for(int i=j;i<=n;++i) 19 #define D(i,j,n) for(int i=j;i>=n;--i) 20 #define pb push_back 21 using namespace std; 22 typedef long long LL; 23 inline int getint(){ 24 int r=1,v=0; char ch=getchar(); 25 for(;!isdigit(ch);ch=getchar()) if (ch=='-') r=-1; 26 for(; isdigit(ch);ch=getchar()) v=v*10-'0'+ch; 27 return r*v; 28 } 29 const int N=10010; 30 /*******************template********************/ 31 32 int B,n,m,col[N],blockid[N]; 33 struct ques{ 34 int l,r,ti,num; 35 bool operator < (const ques &now)const { 36 if (blockid[l]==blockid[now.l]){ 37 if (blockid[r]==blockid[now.r]) return ti<now.ti; 38 else return blockid[r]<blockid[now.r]; 39 }else return blockid[l]<blockid[now.l]; 40 } 41 }q[N]; 42 struct Time{ 43 int x,y,pre; 44 }change[N]; 45 46 int pre[N]; 47 48 bool used[N]; 49 int ans=0,answer[N],now; 50 int cnt[1000010]; 51 /*********************var***********************/ 52 inline void work(int x){ 53 if (used[x]){ 54 cnt[col[x]]--; if (cnt[col[x]]==0) ans--; 55 }else{ 56 cnt[col[x]]++; if (cnt[col[x]]==1) ans++; 57 } 58 used[x]^=1; 59 } 60 inline void Change(int x,int y){ 61 if (used[x]){work(x); col[x]=y; work(x);} 62 else col[x]=y; 63 } 64 inline void Timego(int tarti){ 65 for(int i=now+1;i<=tarti;i++) Change(change[i].x,change[i].y); 66 for(int i=now;i>tarti;i--) Change(change[i].x,change[i].pre); 67 now=tarti; 68 } 69 /*********************func**********************/ 70 int main(){ 71 #ifndef ONLINE_JUDGE 72 freopen("2120.in","r",stdin); 73 freopen("2120.out","w",stdout); 74 #endif 75 n=getint(); m=getint(); 76 B=pow(n,2.0/3.0); 77 F(i,1,n){ 78 pre[i]=col[i]=getint(); 79 blockid[i]=(i-1)/B+1; 80 } 81 char cmd[5]; 82 int c1=0,c2=0; 83 F(i,1,m){ 84 scanf("%s",cmd); 85 int x=getint(),y=getint(); 86 if (cmd[0]=='Q'){ 87 c2++; 88 q[c2]=(ques){x,y,c1,c2}; 89 }else{ 90 c1++; 91 change[c1]=(Time){x,y,pre[x]}; 92 pre[x]=y; 93 } 94 } 95 sort(q+1,q+c2+1); 96 Timego(q[1].ti); 97 int l=q[1].l,r=q[1].r; 98 F(i,l,r) work(i); 99 answer[q[1].num]=ans; 100 F(i,2,c2){ 101 Timego(q[i].ti); 102 F(j,min(l,q[i].l),max(l,q[i].l)-1) work(j); 103 l=q[i].l; 104 F(j,min(r,q[i].r)+1,max(r,q[i].r)) work(j); 105 r=q[i].r; 106 answer[q[i].num]=ans; 107 } 108 F(i,1,c2) printf("%d ",answer[i]); 109 return 0; 110 } 111
2120: 数颜色
Time Limit: 6 Sec Memory Limit: 259 MBSubmit: 1832 Solved: 716
[Submit][Status][Discuss]
Description
墨 墨购买了一套N支彩色画笔(其中有些颜色可能相同),摆成一排,你需要回答墨墨的提问。墨墨会像你发布如下指令: 1、 Q L R代表询问你从第L支画笔到第R支画笔中共有几种不同颜色的画笔。 2、 R P Col 把第P支画笔替换为颜色Col。为了满足墨墨的要求,你知道你需要干什么了吗?
Input
第1行两个整数N,M,分别代表初始画笔的数量以及墨墨会做的事情的个数。第2行N个整数,分别代表初始画笔排中第i支画笔的颜色。第3行到第2+M行,每行分别代表墨墨会做的一件事情,格式见题干部分。
Output
对于每一个Query的询问,你需要在对应的行中给出一个数字,代表第L支画笔到第R支画笔中共有几种不同颜色的画笔。
Sample Input
6 5
1 2 3 4 5 5
Q 1 4
Q 2 6
R 1 2
Q 1 4
Q 2 6
1 2 3 4 5 5
Q 1 4
Q 2 6
R 1 2
Q 1 4
Q 2 6
Sample Output
4
4
3
4
4
3
4
HINT
对于100%的数据,N≤10000,M≤10000,修改操作不多于1000次,所有的输入数据中出现的所有整数均大于等于1且不超过10^6。