BZOJ 1858: [Scoi2010]序列操作 线段树区间修改查询

时空隧道


其实这道题没有什么特殊的地方….就是一定不要用cin&cout会RE…
还有就是合并lazy的标记的时候一定要想清楚…(我把-1写成1查了半天…)


代码如下:

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
//by NeighThorn
using namespace std;
const int maxn=100000+5;
int n,m,pri[maxn];
struct Tree{
    int l,r,pre0,suf0,seq0,pre1,suf1,seq1,No1,len,lazy;
}tree[maxn*4];
inline void build(int l,int r,int tr){
    tree[tr].l=l,tree[tr].r=r;tree[tr].len=tree[tr].r-tree[tr].l+1;tree[tr].lazy=-1;
    if(l==r){
        if(pri[l]==0)
            tree[tr].pre0=1,tree[tr].suf0=1,tree[tr].seq0=1,tree[tr].pre1=tree[tr].suf1=tree[tr].seq1=0,tree[tr].No1=0;
        else
            tree[tr].pre1=1,tree[tr].suf1=1,tree[tr].seq1=1,tree[tr].pre0=tree[tr].suf0=tree[tr].seq0=0,tree[tr].No1=1;
        return;
    }
    int mid=(l+r)>>1;
    build(l,mid,tr<<1),build(mid+1,r,tr<<1|1);
    if(tree[tr<<1].pre0==tree[tr<<1].len)
        tree[tr].pre0=tree[tr<<1].len+tree[tr<<1|1].pre0;
    else
        tree[tr].pre0=tree[tr<<1].pre0;
    if(tree[tr<<1|1].suf0==tree[tr<<1|1].len)
        tree[tr].suf0=tree[tr<<1|1].len+tree[tr<<1].suf0;
    else
        tree[tr].suf0=tree[tr<<1|1].suf0;
    tree[tr].seq0=max(tree[tr<<1].seq0,tree[tr<<1|1].seq0);
    tree[tr].seq0=max(tree[tr].seq0,tree[tr<<1].suf0+tree[tr<<1|1].pre0);
    if(tree[tr<<1].pre1==tree[tr<<1].len)
        tree[tr].pre1=tree[tr<<1].len+tree[tr<<1|1].pre1;
    else
        tree[tr].pre1=tree[tr<<1].pre1;
    if(tree[tr<<1|1].suf1==tree[tr<<1|1].len)
        tree[tr].suf1=tree[tr<<1|1].len+tree[tr<<1].suf1;
    else
        tree[tr].suf1=tree[tr<<1|1].suf1;
    tree[tr].seq1=max(tree[tr<<1].seq1,tree[tr<<1|1].seq1);
    tree[tr].seq1=max(tree[tr].seq1,tree[tr<<1].suf1+tree[tr<<1|1].pre1);
    tree[tr].No1=tree[tr<<1].No1+tree[tr<<1|1].No1;
}
inline void change(int l,int r,int order,int tr){
//  cout<<l<<" "<<r<<" "<<tree[tr].l<<" "<<tree[tr].r<<" "<<tree[tr].lazy<<" "<<order<<endl;
    if(tree[tr].l==l&&tree[tr].r==r){
        if(order==0)
            tree[tr].pre0=tree[tr].suf0=tree[tr].seq0=tree[tr].len,
            tree[tr].pre1=tree[tr].suf1=tree[tr].seq1=tree[tr].No1=0;
        else if(order==1)
            tree[tr].pre0=tree[tr].suf0=tree[tr].seq0=0,
            tree[tr].pre1=tree[tr].suf1=tree[tr].seq1=tree[tr].No1=tree[tr].len;
        else if(order==2)
            swap(tree[tr].pre0,tree[tr].pre1),swap(tree[tr].suf0,tree[tr].suf1),swap(tree[tr].seq0,tree[tr].seq1),
            tree[tr].No1=tree[tr].len-tree[tr].No1;
        if(order!=2)    
            tree[tr].lazy=order;
        else if(tree[tr].lazy==-1)
            tree[tr].lazy=order;
        else if(tree[tr].lazy!=2)
            tree[tr].lazy^=1;
        else if(tree[tr].lazy==2)
            tree[tr].lazy=-1;
        return;
    }
    int mid=(tree[tr].l+tree[tr].r)>>1;
    if(tree[tr].lazy!=-1)
        change(tree[tr].l,mid,tree[tr].lazy,tr<<1),change(mid+1,tree[tr].r,tree[tr].lazy,tr<<1|1),tree[tr].lazy=-1;
    if(r<=mid)
        change(l,r,order,tr<<1);
    else if(l>mid)
        change(l,r,order,tr<<1|1);
    else
        change(l,mid,order,tr<<1),change(mid+1,r,order,tr<<1|1);
    if(tree[tr<<1].pre0==tree[tr<<1].len)
        tree[tr].pre0=tree[tr<<1].len+tree[tr<<1|1].pre0;
    else
        tree[tr].pre0=tree[tr<<1].pre0;
    if(tree[tr<<1|1].suf0==tree[tr<<1|1].len)
        tree[tr].suf0=tree[tr<<1|1].len+tree[tr<<1].suf0;
    else
        tree[tr].suf0=tree[tr<<1|1].suf0;
    tree[tr].seq0=max(tree[tr<<1].seq0,tree[tr<<1|1].seq0);
    tree[tr].seq0=max(tree[tr].seq0,tree[tr<<1].suf0+tree[tr<<1|1].pre0);
    if(tree[tr<<1].pre1==tree[tr<<1].len)
        tree[tr].pre1=tree[tr<<1].len+tree[tr<<1|1].pre1;
    else
        tree[tr].pre1=tree[tr<<1].pre1;
    if(tree[tr<<1|1].suf1==tree[tr<<1|1].len)
        tree[tr].suf1=tree[tr<<1|1].len+tree[tr<<1].suf1;
    else
        tree[tr].suf1=tree[tr<<1|1].suf1;
    tree[tr].seq1=max(tree[tr<<1].seq1,tree[tr<<1|1].seq1);
    tree[tr].seq1=max(tree[tr].seq1,tree[tr<<1].suf1+tree[tr<<1|1].pre1);
    tree[tr].No1=tree[tr<<1].No1+tree[tr<<1|1].No1;
}
inline int query(int l,int r,int order,int tr){
    if(tree[tr].l==l&&tree[tr].r==r){
        if(order==3)
            return tree[tr].No1;
        else if(order==4)
            return tree[tr].seq1;
        else if(order==5)
            return tree[tr].pre1;
        else
            return tree[tr].suf1;
    }
    int mid=(tree[tr].l+tree[tr].r)>>1;
    if(tree[tr].lazy!=-1)
        change(tree[tr].l,mid,tree[tr].lazy,tr<<1),change(mid+1,tree[tr].r,tree[tr].lazy,tr<<1|1),tree[tr].lazy=-1;
    if(r<=mid)
        return query(l,r,order,tr<<1);
    else if(l>mid)
        return query(l,r,order,tr<<1|1);
    else{
        if(order==3)
            return query(l,mid,order,tr<<1)+query(mid+1,r,order,tr<<1|1);
        else if(order==4){
            int lala=max(query(l,mid,order,tr<<1),query(mid+1,r,order,tr<<1|1));
            lala=max(lala,query(l,mid,6,tr<<1)+query(mid+1,r,5,tr<<1|1));
            return lala;
        }
        else if(order==5){
            int lala=query(l,mid,order,tr<<1);
            if(lala==mid-l+1)
                lala+=query(mid+1,r,order,tr<<1|1);
            return lala;
        }
        else{
            int lala=query(mid+1,r,order,tr<<1|1);
            if(lala==r-mid)
                lala+=query(l,mid,order,tr<<1);
            return lala;
        }
    }
}
signed main(void){
//  freopen("in.txt","r",stdin);
//  freopen("out1.txt","w",stdout);
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
        scanf("%d",&pri[i]);
    build(1,n,1);int s,x,y;
    while(m--){
        scanf("%d%d%d",&s,&x,&y);x++,y++;
        if(s>=0&&s<=2)
            change(x,y,s,1);//,cout<<"lala"<<query(1,6,3,1)<<" lalala"<<query(1,6,4,1)<<endl;
        else
            printf("%d\n",query(x,y,s,1));
    }
    return 0;
}

by >_< NeighThorn

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值