bzoj1858: [Scoi2010]序列操作

就是写数据结构啊。。就连线段树都写这么久啊。。

本来以为这题应该就是线段树的两个遗传标记的解决,应该跟splay差不多,结果这题不一样。

主要的难点就是遗传标记的下放了。对于这里的翻转标记,他的实际意义应该是改值,所以应该是两个改值操作,跟之前做过的一道区间增加和区间乘操作一样,一个操作会影响另一个操作,操作的顺序不同会改变值,也就是不满足交换律。

对于这个问题,我的做法是记录修改的时间,比较两种修改的顺序,然后有一个注意的地方,就是连续反转两次时,re^=1,re^=1,此时re变回0,也就是不反转,那么假如在两次反转中有一次改值的操作,那么第一次反转失效,所以当改值的时候,把反转清空就行了。

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;

struct seq
{
    int l,r,lc,rc;
    int sum[2],lie[2],lef[2],rig[2];
    int re,ch,rt,ct;
}tr[210000];int trlen;

int a[110000];
void update(int now,int lc,int rc)
{    
    tr[now].sum[0]=tr[lc].sum[0]+tr[rc].sum[0];
    tr[now].sum[1]=tr[lc].sum[1]+tr[rc].sum[1];
    
    tr[now].lie[0]=max( max(tr[lc].lie[0],tr[rc].lie[0]) , tr[lc].rig[0]+tr[rc].lef[0] );
    tr[now].lie[1]=max( max(tr[lc].lie[1],tr[rc].lie[1]) , tr[lc].rig[1]+tr[rc].lef[1] );
    
    int t;
    
    t=tr[lc].r-tr[lc].l+1;
    if(tr[lc].lef[0]!=t)tr[now].lef[0]=tr[lc].lef[0];
    else  tr[now].lef[0]=tr[lc].lef[0]+tr[rc].lef[0];
    if(tr[lc].lef[1]!=t)tr[now].lef[1]=tr[lc].lef[1];
    else  tr[now].lef[1]=tr[lc].lef[1]+tr[rc].lef[1];
    
    t=tr[rc].r-tr[rc].l+1;
    if(tr[rc].rig[0]!=t)tr[now].rig[0]=tr[rc].rig[0];
    else  tr[now].rig[0]=tr[rc].rig[0]+tr[lc].rig[0];
    if(tr[rc].rig[1]!=t)tr[now].rig[1]=tr[rc].rig[1];
    else  tr[now].rig[1]=tr[rc].rig[1]+tr[lc].rig[1];
}
void mychud(int now,int k,int t)
{
    tr[now].ch=k;tr[now].re=0;tr[now].ct=t;
    int d=tr[now].r-tr[now].l+1;
    tr[now].sum[k]=tr[now].lie[k]=tr[now].lef[k]=tr[now].rig[k]=d;
    tr[now].sum[1-k]=tr[now].lie[1-k]=tr[now].lef[1-k]=tr[now].rig[1-k]=0;
}
void myswap(int now,int t)
{    
    tr[now].re^=1;tr[now].rt=t;
    swap(tr[now].sum[0],tr[now].sum[1]);
    swap(tr[now].lie[0],tr[now].lie[1]);
    swap(tr[now].lef[0],tr[now].lef[1]);
    swap(tr[now].rig[0],tr[now].rig[1]);
}
void jicheng(int now,int lc,int rc)
{
    if(tr[now].ct>tr[now].rt)
    {
        if(tr[now].re==1)
        {
            myswap(lc,tr[now].rt);
            myswap(rc,tr[now].rt);
            tr[now].re=0;
        }
        if(tr[now].ch!=-1)
        {
            mychud(lc,tr[now].ch,tr[now].ct);
            mychud(rc,tr[now].ch,tr[now].ct);
            tr[now].ch=-1;
        }
    }
    else
    {
        if(tr[now].ch!=-1)
        {
            mychud(lc,tr[now].ch,tr[now].ct);
            mychud(rc,tr[now].ch,tr[now].ct);
            tr[now].ch=-1;
        }
        if(tr[now].re==1)
        {
            myswap(lc,tr[now].rt);
            myswap(rc,tr[now].rt);
            tr[now].re=0;
        }
    }
}

//-----------basic-----------------------

void add(int l,int now)
{
    tr[now].sum[a[l]]=1;tr[now].sum[1-a[l]]=0;
    tr[now].lie[a[l]]=1;tr[now].lie[1-a[l]]=0;
    tr[now].lef[a[l]]=1;tr[now].lef[1-a[l]]=0;
    tr[now].rig[a[l]]=1;tr[now].rig[1-a[l]]=0;
}
void bt(int l,int r)
{
    trlen++;int now=trlen;
    tr[now].l=l;tr[now].r=r;
    tr[now].lc=tr[now].rc=0;
    tr[now].re=0;tr[now].ch=-1;
    tr[now].rt=-1;tr[now].ct=-1;
    
    if(l==r)add(l,now);
    else
    {
        int mid=(l+r)/2;
        tr[now].lc=trlen+1;bt(l,mid);
        tr[now].rc=trlen+1;bt(mid+1,r);
        update(now,tr[now].lc,tr[now].rc);
    }
}

//-----------build tree------------

void change(int now,int l,int r,int k,int t)
{
    if(tr[now].l==l&&tr[now].r==r){mychud(now,k,t);return ;}
    
    int lc=tr[now].lc,rc=tr[now].rc;
    int mid=(tr[now].l+tr[now].r)/2;
    
    jicheng(now,lc,rc);
    
         if(r<=mid)  change(lc,l,r,k,t);
    else if(mid+1<=l)change(rc,l,r,k,t);
    else change(lc,l,mid,k,t), change(rc,mid+1,r,k,t);
    
    update(now,lc,rc);
}
void reverse(int now,int l,int r,int t)
{
    if(tr[now].l==l&&tr[now].r==r){myswap(now,t);return ;}
    
    int lc=tr[now].lc,rc=tr[now].rc;
    int mid=(tr[now].l+tr[now].r)/2;
    
    jicheng(now,lc,rc);
    
         if(r<=mid)  reverse(lc,l,r,t);
    else if(mid+1<=l)reverse(rc,l,r,t);
    else reverse(lc,l,mid,t), reverse(rc,mid+1,r,t);
    
    update(now,lc,rc);
}

//----------change-----------

int asksum(int now,int l,int r)
{
    if(tr[now].l==l&&tr[now].r==r)return tr[now].sum[1];
    
    int lc=tr[now].lc,rc=tr[now].rc;
    int mid=(tr[now].l+tr[now].r)/2;
    
    jicheng(now,lc,rc);
    
         if(r<=mid)  return asksum(lc,l,r);
    else if(mid+1<=l)return asksum(rc,l,r);
    else return asksum(lc,l,mid)+asksum(rc,mid+1,r);        
}
int asklie(int now,int l,int r)
{
    if(tr[now].l==l&&tr[now].r==r)return tr[now].lie[1];
    
    int lc=tr[now].lc,rc=tr[now].rc;
    int mid=(tr[now].l+tr[now].r)/2;
    
    jicheng(now,lc,rc);
    
         if(r<=mid)  return asklie(lc,l,r);
    else if(mid+1<=l)return asklie(rc,l,r);
    else return max( max(asklie(lc,l,mid),asklie(rc,mid+1,r)) , min(tr[lc].r-l+1,tr[lc].rig[1]) + min(r-tr[rc].l+1,tr[rc].lef[1]) );
}

//---------ask------------

void dfs(int now)
{
    if(tr[now].l==tr[now].r)
    {
        printf("%d ",tr[now].sum[0]==0?1:0);
        return ;
    }
    jicheng(now,tr[now].lc,tr[now].rc);
    dfs(tr[now].lc);
    dfs(tr[now].rc);
}
int main()
{
    //freopen("operation.in","r",stdin);
    //freopen("operation.out","w",stdout);
    int n,m;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        for(int i=1;i<=n;i++)scanf("%d",&a[i]);
        trlen=0;bt(1,n);
        
        int op,x,y;
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d%d",&op,&x,&y);x++;y++;
            if(op==0||op==1)change(1,x,y,op,i);
            else if(op==2)reverse(1,x,y,i);
            else if(op==3)printf("%d\n",asksum(1,x,y));
            else if(op==4)printf("%d\n",asklie(1,x,y));
            
            //dfs(1);printf("\n");
        }
    }
    return 0;
}

 

posted @ 2018-01-11 13:07  AKCqhzdy  阅读(155)  评论(0编辑  收藏  举报