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 }

 

posted @ 2017-11-16 22:18  社会主义市场经济  阅读(228)  评论(0编辑  收藏  举报