[线段树] Jzoj P1214 项链工厂
题解
- 主要是翻转和旋转操作比较奇怪,其他都是线段树基本操作
- 一个是顺时针旋转,如果不存在翻转操作
- 我们显然可以通过记录顺时针旋转的次数来还原当前的一号位置
- 多了一个翻转
- 仔细观察,就是把顺时针变为了逆时针而已
- 所以直接乘个负号,额外加一个标记就行了
代码
1 #include <cstdio> 2 #include <iostream> 3 #include <cstring> 4 using namespace std; 5 bool rev; 6 char ch[5]; 7 int n,m,p; 8 struct data{int l,r,sum;}; 9 struct tree{int l,r,tag;data v;}t[2000005]; 10 data merge(data a,data b) 11 { 12 data r={a.l,b.r,a.sum+b.sum}; 13 if (a.r==b.l) r.sum--; 14 return r; 15 } 16 void calc(int &x,int &y) 17 { 18 if (rev) x=(n*2+2-p-x)%n,y=(n*2+2-p-y)%n,swap(x,y); 19 else x=(x-p+n)%n,y=(y-p+n)%n; 20 if (x==0) x=n; 21 if (y==0) y=n; 22 } 23 void pushdown(int d) 24 { 25 if (!t[d].tag||t[d].l==t[d].r) return; 26 int r=t[d].tag; t[d].tag=0; 27 t[d*2].tag=t[d*2+1].tag=t[d*2].v.l=t[d*2+1].v.l=t[d*2].v.r=t[d*2+1].v.r=r; 28 t[d*2].v.sum=t[d*2+1].v.sum=1; 29 } 30 void build(int d,int l,int r) 31 { 32 t[d].l=l,t[d].r=r; 33 if (l==r) 34 { 35 scanf("%d",&t[d].v.l),t[d].v.r=t[d].v.l,t[d].v.sum=1; 36 return; 37 } 38 int mid=l+r>>1; 39 build(d*2,l,mid),build(d*2+1,mid+1,r),t[d].v=merge(t[d*2].v,t[d*2+1].v); 40 } 41 data query(int d,int l,int r) 42 { 43 pushdown(d); 44 int L=t[d].l,R=t[d].r; 45 if (l==L&&r==R) return t[d].v; 46 int mid=L+R>>1; 47 if (r<=mid) return query(d*2,l,r); else if (l>mid) return query(d*2+1,l,r); else return merge(query(d*2,l,mid),query(d*2+1,mid+1,r)); 48 } 49 void modify(int d,int l,int r,int x) 50 { 51 pushdown(d); 52 int L=t[d].l,R=t[d].r; 53 if (l==L&&R==r) 54 { 55 t[d].v.l=t[d].v.r=t[d].tag=x,t[d].v.sum=1; 56 return; 57 } 58 int mid=L+R>>1; 59 if (r<=mid) modify(d*2,l,r,x); else if (l>mid) modify(d*2+1,l,r,x); else modify(d*2,l,mid,x),modify(d*2+1,mid+1,r,x); 60 t[d].v=merge(t[d*2].v,t[d*2+1].v); 61 } 62 int main() 63 { 64 freopen("data.in","r",stdin); 65 scanf("%d%d",&n,&m),build(1,1,n),scanf("%d",&m); 66 for (int x,y,z;m;m--) 67 { 68 scanf("%s",ch); 69 if (ch[0]=='R') 70 { 71 scanf("%d",&x); 72 if (rev) p=(p+n-x)%n; else p=(p+x)%n; 73 } 74 if (ch[0]=='F') rev^=1; 75 if (ch[0]=='S') 76 { 77 int a,b; data ans; 78 scanf("%d%d",&x,&y),calc(x,y); 79 if (x>y) ans=query(1,y,x),a=ans.r,b=ans.l; else ans=query(1,x,y),a=ans.l,b=ans.r; 80 modify(1,x,x,b),modify(1,y,y,a); 81 } 82 if (ch[0]=='P') 83 { 84 scanf("%d%d%d",&x,&y,&z),calc(x,y); 85 if (x<=y) modify(1,x,y,z); else modify(1,x,n,z),modify(1,1,y,z); 86 } 87 if (ch[0]=='C'&&ch[1]=='S') 88 { 89 scanf("%d%d",&x,&y),calc(x,y); data ans; 90 if (x<=y) ans=query(1,x,y); else ans=merge(query(1,x,n),query(1,1,y)); 91 printf("%d\n",ans.sum); 92 } 93 if (ch[0]=='C'&&ch[1]!='S') 94 { 95 data ans=query(1,1,n); 96 int r=ans.sum; 97 if (ans.l==ans.r) r=max(r-1,1); 98 printf("%d\n",r); 99 } 100 } 101 }