bzoj 1493: [NOI2007]项链工厂(线段树)
1493: [NOI2007]项链工厂
Time Limit: 30 Sec Memory Limit: 64 MBSubmit: 1256 Solved: 545
[Submit][Status][Discuss]
Description
Input
输 入文件第一行包含两个整数N, c,分别表示项链包含的珠子数目以及颜色 数目。第二行包含N 个整数,x1, x2…, xn,表示从位置1 到位置N 的珠子的颜色, 1 ≤ xi ≤ c。第三行包含一个整数Q,表示命令数目。接下来的Q 行每行一条命令, 如上文所述。
Output
对于每一个C 和CS 命令,应输出一个整数代表相应的答案。
Sample Input
5 3
1 2 3 2 1
4
C
R 2
P 5 5 2
CS 4 1
1 2 3 2 1
4
C
R 2
P 5 5 2
CS 4 1
Sample Output
4
1
1
HINT
对于60%的数据,N ≤ 1 000,Q ≤ 1 000; 对于100%的数据,N ≤ 500 000,Q ≤ 500 000,c ≤ 1 000。
【思路】
线段树。
R F之后虽然珠子的顺序变了,但是相对顺序是不变的。
我们用MOV记录顺时针旋转量,F记录是否翻转。
如果翻转则MOV-=k,否则MOV+=k。然后用MOV计算出查询位置对应的原位置,在原位置上进行操作。
剩下的就是区间上的颜色修改以及统计颜色段数的问题了,可以用线段树完成。
注意珠子是环形的,别忘比较一下1和n的颜色。
【代码】
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<algorithm> 5 #define FOR(a,b,c) for(int a=(b);a<=(c);a++) 6 using namespace std; 7 8 const int N = 5*1e5+10; 9 int n,m,c,MOV,F,co[N]; 10 //SEGMENT TREE 11 struct Trie{ int l,r,s,c,lc,rc,setv; }T[N*4]; 12 void pushdown(int u) { 13 if(T[u].l<T[u].r && T[u].setv!=-1) { 14 int lc=u<<1,rc=lc|1; 15 T[lc].c=T[rc].c=T[lc].setv=T[rc].setv=T[u].setv; 16 T[lc].lc=T[lc].rc=T[rc].lc=T[rc].rc=T[u].setv; 17 T[lc].s=T[rc].s=1; 18 T[u].setv=-1; 19 } 20 } 21 void maintain(int u) { 22 int lc=u<<1,rc=lc|1; 23 T[u].s=T[lc].s+T[rc].s-(T[lc].rc==T[rc].lc); 24 T[u].lc=T[lc].lc,T[u].rc=T[rc].rc; 25 } 26 void build(int u,int L,int R) { 27 T[u].l=L,T[u].r=R; T[u].setv=-1; 28 if(L==R) { 29 T[u].c=T[u].lc=T[u].rc=co[L]; T[u].s=1; 30 return ; 31 } 32 int M=(L+R)>>1; 33 build(u<<1,L,M) , build(u<<1|1,M+1,R); 34 maintain(u); 35 } 36 void update(int u,int L,int R,int x) { 37 pushdown(u); 38 if(L<=T[u].l && T[u].r<=R) { 39 T[u].setv=T[u].c=T[u].lc=T[u].rc=x; 40 T[u].s=1; 41 } 42 else { 43 int M=(T[u].l+T[u].r)>>1; 44 if(L<=M) update(u<<1,L,R,x); 45 if(M<R) update(u<<1|1,L,R,x); 46 maintain(u); 47 } 48 } 49 int query(int u,int L,int R) { 50 pushdown(u); 51 if(L==T[u].l && T[u].r==R) { 52 return T[u].s; 53 } 54 else { 55 int M=(T[u].l+T[u].r)>>1; 56 if(R<=M) return query(u<<1,L,R); 57 else if(L>M) return query(u<<1|1,L,R); 58 else { 59 int ans=query(u<<1,L,M); 60 ans+=query(u<<1|1,M+1,R); 61 ans-=T[u<<1].rc==T[u<<1|1].lc; 62 return ans; 63 } 64 } 65 } 66 int getcolor(int u,int x) { 67 pushdown(u); 68 if(T[u].l==T[u].r) return T[u].c; 69 else { 70 int M=(T[u].l+T[u].r)>>1; 71 if(x<=M) return getcolor(u<<1,x); 72 else return getcolor(u<<1|1,x); 73 } 74 } 75 76 int get(int x) { 77 if(F) x=n+2-x; 78 x-=MOV; 79 while(x<1) x+=n; 80 while(x>n) x-=n; 81 return x; 82 } 83 void read(int& x) { 84 char c=getchar(); x=0; int f=1; 85 while(!isdigit(c)){if(c=='-')f=-1;c=getchar();} 86 while(isdigit(c)) x=x*10+c-'0',c=getchar(); 87 } 88 int main() { 89 freopen("in.in","r",stdin); 90 freopen("out.out","w",stdout); 91 read(n),read(c); 92 int x,a,b,c; char s[5]; 93 for(int i=1;i<=n;i++) read(co[i]); 94 build(1,1,n); 95 read(m); 96 while(m--) { 97 scanf("%s",s); 98 if(s[0]=='R') { 99 read(a); 100 if(F) MOV-=a; else MOV+=a; 101 while(MOV<0) MOV+=n; 102 while(MOV>n) MOV-=n; 103 } else 104 if(s[0]=='F') F^=1; else 105 if(s[0]=='S') { 106 read(a),read(b); 107 a=get(a),b=get(b); 108 int c1=getcolor(1,a),c2=getcolor(1,b); 109 update(1,a,a,c2),update(1,b,b,c1); 110 } else 111 if(s[0]=='P') { 112 read(a),read(b),read(c); 113 a=get(a),b=get(b); 114 if(F) swap(a,b); 115 if(a>b) update(1,a,n,c),update(1,1,b,c); 116 else update(1,a,b,c); 117 } else 118 if(s[0] && strlen(s)==1) { 119 int ans=query(1,1,n); 120 if(ans>1&&T[1].lc==T[1].rc) ans--; 121 printf("%d\n",ans); 122 } else { 123 read(a),read(b); 124 a=get(a),b=get(b); 125 if(F) swap(a,b); 126 int ans; 127 if(a<=b) { 128 ans=query(1,a,b); 129 if(a==1&&b==n&&ans>1&&T[1].lc==T[1].rc) ans--; 130 } else { 131 ans=query(1,a,n)+query(1,1,b); 132 if(T[1].lc==T[1].rc) ans--; 133 } 134 printf("%d\n",ans); 135 } 136 } 137 return 0; 138 }
posted on 2016-02-16 08:47 hahalidaxin 阅读(290) 评论(0) 编辑 收藏 举报