bzoj1493: [NOI2007]项链工厂

来源:互联网 发布:电视机怎么看网络电视 编辑:程序博客网 时间:2024/06/10 03:49

传送门
能不用splay坚决不用splay—–zyy
这道题如果没有旋转翻转操作的话就是一道区间修改,区间查询的线段树水题。
那么对于R,F操作应该怎么处理呢?
其实R,F操作之后珠子的相对位置没变
通俗来说就是一个珠子左右两边的珠子还是原来那两个
所以对于R,F操作我们只需要分别记录两个量即可:mov,rev
1.mov:表示当前整体顺时针移动了mov(即k变成k+mov)
输入R k,分两种情况:
没有被翻转过,mov+=k;
被翻转过,mov-=k
2.rev:表示当前是否被翻转过
输入F,直接rev^=1
然后线段树就水过了。

#include<iostream>#include<cstdio>#include<algorithm>#include<cstring>#include<cmath>#include<cstdlib>#define ls x*2#define rs x*2+1using namespace std;struct node{int l,r,tag,lc,rc,sum;}t[2000005];int n,cnt,m,x,y,z,ans,rev=0,mov=0,co[500005];char ch[10];void get(int &a){    if (rev) a=n-a+2;    a-=mov;    for (;a>n;a-=n);    for (;a<1;a+=n);}void pushup(int x){    t[x].lc=t[ls].lc;    t[x].rc=t[rs].rc;    t[x].sum=t[ls].sum+t[rs].sum;    if (t[ls].rc==t[rs].lc) t[x].sum--;}void pushdown(int x){    if (!t[x].tag) return;    t[ls].tag=t[rs].tag=t[x].tag;    t[ls].lc=t[ls].rc=t[rs].lc=t[rs].rc=t[x].tag;    t[ls].sum=t[rs].sum=1;    t[x].tag=0;}node merge(node a,node b){    node tmp;    tmp.sum=a.sum+b.sum;    tmp.lc=a.lc; tmp.rc=b.rc;    if (a.rc==b.lc) tmp.sum--;    return tmp;}void build(int x,int l,int r){    t[x].l=l; t[x].r=r;    t[x].tag=0;    if (l==r){        t[x].lc=t[x].rc=t[x].tag=co[l];        t[x].sum=1;        return;    }    int mid=(l+r)/2;    build(ls,l,mid);    build(rs,mid+1,r);    pushup(x);}int color(int x,int y){    int l=t[x].l,r=t[x].r,mid=(l+r)/2;    if (l==r) return t[x].lc;    pushdown(x);    if (y<=mid) return color(ls,y);    return color(rs,y);}void change(int x,int p,int q,int v){    int l=t[x].l,r=t[x].r,mid=(l+r)/2;    if (l==p&&r==q){        t[x].lc=t[x].rc=t[x].tag=v;        t[x].sum=1;        return;    }    pushdown(x);    if (q<=mid) change(ls,p,q,v);    else if (p>mid) change(rs,p,q,v);    else change(ls,p,mid,v),change(rs,mid+1,q,v);    pushup(x);}node ask(int x,int p,int q){    int l=t[x].l,r=t[x].r,mid=(l+r)/2;    if (l==p&&r==q) return t[x];    pushdown(x);    if (q<=mid) return ask(ls,p,q);    if (p>mid) return ask(rs,p,q);    return merge(ask(ls,p,mid),ask(rs,mid+1,q));}int main(){    scanf("%d%d",&n,&cnt);    for (int i=1;i<=n;i++) scanf("%d",&co[i]);    build(1,1,n);    scanf("%d",&m);    while (m--){        scanf("%s",ch);        if (ch[0]=='R'){            scanf("%d",&x);            if (rev) mov-=x; else mov+=x;            for (;mov>n;mov-=n);            for (;mov<0;mov+=n);        }        if (ch[0]=='F') rev^=1;        if (ch[0]=='S'){            scanf("%d%d",&x,&y);            get(x); get(y);            int xx=color(1,x),yy=color(1,y);            change(1,x,x,yy);            change(1,y,y,xx);        }        if (ch[0]=='P'){            scanf("%d%d%d",&x,&y,&z);            get(x); get(y);            if (rev) swap(x,y);            if (x>y) change(1,x,n,z),change(1,1,y,z);            else change(1,x,y,z);        }        if (ch[0]=='C'){            if (ch[1]=='S'){                scanf("%d%d",&x,&y);                get(x); get(y);                if (rev) swap(x,y);                if (x<=y){                    ans=ask(1,x,y).sum;                    if (x==1&&y==n&&ans>1&&t[1].lc==t[1].rc) ans--;                }                else{                    ans=ask(1,x,n).sum+ask(1,1,y).sum;                    if (t[1].lc==t[1].rc) ans--;                }            }            else{                ans=t[1].sum;                if (ans>1&&t[1].lc==t[1].rc) ans--;            }            printf("%d\n",ans);        }    }}
0 0
原创粉丝点击