BZOJ1493 NOI2007 项链工厂 线段树模拟
提交地址:http://www.lydsy.com/JudgeOnline/problem.php?id=1493
题目大意:给一个数列,进行一系列操作。包括旋转,翻转,改变等操作,以及查询颜色段数。
题目分析:数列中元素的相对位置没有改变,因此不需要用splay去做,而是可以用线段树解决这类问题。
旋转操作直接改变变量rotate,翻转操作用异或即可。每次询问先利用rotate求出当前1号位是谁,这样可以根据翻转标记确定区间。如果区间跨越n,那么合并的时候要考虑左边一段的右端和右边一段的左端。相同的时候答案要减少1.
对于swap操作,由于是单点的,可以暴力在树上做。
这题以我的代码水平来说比较难打。
代码如下:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstdlib> 4 #include<cstring> 5 #include<algorithm> 6 using namespace std; 7 8 const int maxn = 600010; 9 struct node{ 10 int lazy; 11 int lft,rgt,tot,full; 12 }t[maxn<<2]; 13 int n,c; 14 int x[maxn]; 15 int fz,rt; // fanzhuan rotate 16 int tl,tr; 17 18 void push_down(int now){ 19 t[now<<1].lazy = t[now<<1|1].lazy = t[now].lazy; 20 t[now].lft = t[now].rgt = t[now].lazy; t[now].tot = 1; 21 t[now].lazy = 0;t[now].full = 1; 22 } 23 24 void push_up(int now){ 25 int L=(now<<1),R = L+1; 26 if(t[now].lazy)push_down(now); 27 if(t[L].lazy)push_down(L); if(t[R].lazy) push_down(R); 28 t[now].lft = t[L].lft; t[now].rgt = t[R].rgt; 29 t[now].tot = t[L].tot + t[R].tot; 30 if(t[L].rgt == t[R].lft) t[now].tot--; 31 if(t[L].full && t[R].full && t[L].rgt == t[R].rgt) t[now].full=1; 32 else t[now].full = 0; 33 } 34 35 void build_tree(int l,int r,int now){ 36 if(l == r){ 37 t[now].lazy = 0; t[now].lft = x[l]; t[now].rgt = x[l]; 38 t[now].tot = 1;t[now].full = 1; 39 }else{ 40 int mid = (l+r>>1);int L=(now<<1),R = L+1; 41 build_tree(l,mid,L); build_tree(mid+1,r,R); 42 push_up(now); 43 } 44 } 45 46 void read(){ 47 scanf("%d%d",&n,&c); 48 for(int i=1;i<=n;i++){ 49 scanf("%d",&x[i]); 50 } 51 build_tree(1,n,1); 52 } 53 54 void Rotate(){ 55 int now; scanf("%d",&now); 56 if(fz == 1) rt += (n-now); 57 else rt += now; 58 rt %= n; 59 } 60 61 int get_ans(int l,int r,int now){ 62 if(now == 1) tl = 1,tr = n; 63 if(t[now].lazy) push_down(now); 64 if(tl > r || tr < l) return 0; 65 if(tl >= l && tr <= r) return t[now].tot; 66 int mid = (tl+tr) / 2; 67 int ans = 0; 68 int tmp = tr; tr=mid; 69 int nnow = get_ans(l,r,now<<1); 70 ans += nnow; 71 tr = tmp;tmp = tl; tl = mid+1; 72 int know = get_ans(l,r,now<<1|1); 73 ans += know; 74 tl = tmp; 75 if(tr-tl!=0&&t[now<<1].rgt == t[now<<1|1].lft&&nnow&&know) ans--; 76 push_up(now); 77 return ans; 78 } 79 80 int get_color(int ord,int now){ 81 if(now == 1) tl = 1,tr = n; 82 if(t[now].lazy) {push_down(now);return t[now].lft;} 83 if(tl == tr) return t[now].lft; 84 int mid = (tl+tr)/2; 85 int ans; 86 if(mid >= ord){tr = mid; ans = get_color(ord,now<<1);} 87 else {tl = mid+1; ans = get_color(ord,now<<1|1);} 88 push_up(now); 89 return ans; 90 } 91 92 void Tpaint(int l,int r,int now,int xc){ 93 if(now == 1) tl = 1,tr = n; 94 if(t[now].lazy) {push_down(now);} 95 if(tl > r || tr < l) return; 96 if(tl >= l && tr <= r) {t[now].lazy = xc;push_down(now);return;} 97 int mid = (tl+tr)/2; 98 int tmp = tr;tr = mid; 99 Tpaint(l,r,now<<1,xc); 100 tr = tmp; tmp = tl; tl = mid+1; 101 Tpaint(l,r,now<<1|1,xc); 102 tl = tmp; 103 push_up(now); 104 } 105 106 int cnt; 107 void Count(){ 108 int l,r,flag=0,flag2=0; 109 char ch = getchar(); 110 cnt++; 111 if(ch != 'S') { 112 l = 1,r=n; 113 int ans = t[1].tot-(t[1].lft == t[1].rgt && t[1].full==0); 114 printf("%d\n",ans); 115 return; 116 }else { 117 scanf("%d%d",&l,&r); 118 } 119 int st = (1-rt); if(st <= 0) st += n; 120 if(fz == 1){ 121 l = st-l+1; r = st-r+1; 122 if(l <= 0) l += n; if(r <= 0) r += n; 123 int ans = 0; 124 if(l < r){ 125 ans += get_ans(1,l,1); 126 ans += get_ans(r,n,1); 127 if(t[1].lft == t[1].rgt) ans--; 128 }else ans += get_ans(r,l,1); 129 printf("%d\n",ans); 130 }else{ 131 l = st+l-1; r = st+r-1; 132 if(l > n) l -= n; if(r > n) r -= n; 133 int ans = 0; 134 if(l > r){ 135 ans += get_ans(1,r,1); 136 ans += get_ans(l,n,1); 137 if(t[1].lft == t[1].rgt) ans--; 138 }else ans += get_ans(l,r,1); 139 printf("%d\n",ans); 140 } 141 } 142 143 void Paint(){ 144 int l,r,xc; scanf("%d%d%d",&l,&r,&xc); 145 int st = (1-rt); if(st <= 0) st += n; 146 if(fz == 1){ 147 l = st-l+1; r = st-r+1; 148 if(l <= 0) l += n; if(r <= 0) r += n; 149 if(l < r){ Tpaint(1,l,1,xc); Tpaint(r,n,1,xc);} 150 else Tpaint(r,l,1,xc); 151 }else{ 152 l = st+l-1; r = st+r-1; 153 if(l > n) l -= n; if(r > n) r -= n; 154 if(l > r){ Tpaint(1,r,1,xc); Tpaint(l,n,1,xc);} 155 else Tpaint(l,r,1,xc); 156 } 157 } 158 159 void Swap(){ 160 int l,r; scanf("%d%d",&l,&r); 161 int st = (1-rt); if(st <= 0) st += n; 162 if(fz == 1){ 163 l = st-l+1; r = st-r+1; 164 if(l <= 0) l += n; if(r <= 0) r+= n; 165 }else{ 166 l = st+l-1; r = st+r-1; 167 if(l > n) l -= n; if(r > n) r -= n; 168 } 169 int nowl = get_color(l,1),nowr = get_color(r,1); 170 Tpaint(l,l,1,nowr); Tpaint(r,r,1,nowl); 171 } 172 173 void work(){ 174 int q; scanf("%d",&q); 175 for(int i=1;i<=q;i++){ 176 char ch = getchar(); 177 while(ch > 'Z' || ch < 'A')ch = getchar(); 178 switch(ch){ 179 case 'R':{Rotate();break;} 180 case 'F':{fz ^= 1;break;} 181 case 'S':{Swap();break;} 182 case 'P':{Paint();break;} 183 case 'C':{Count();break;} 184 } 185 } 186 } 187 188 int main(){ 189 //freopen("1.in","r",stdin); 190 //freopen("1.out","w",stdout); 191 read(); 192 work(); 193 return 0; 194 }