bzoj1493: [NOI2007]項鏈工廠


傳送門
能不用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+1
using 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);
        }
    }
}

注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2021 ITdaan.com