Ha^ckansI^LAmattle::oorg@nfnesa::

P2572 [SCOI2010] 序列操作

Seg_Tree @ 2019-10-06 13:44:23

这句话在kysnlmm语中的意思是:这道题我不会,只得了10分,请求巨佬帮助。提交记录

#include <iostream>
#define MaxN 100001
#define fangbian int m=l+r>>1,ls=k<<1,rs=k<<1|1
using namespace std;
struct tree{
    //以下是有关总数的变量 
    int sum;//共有多少1
    //以下是有关连续问题变量 
    int s1;//最大连续1
    int s0;//最大连续0 
    int l1;//最左端有多少连续1
    int r1;//最右端有多少连续1 
    int l0;//最左端有多少连续0
    int r0;//最右端有多少连续0 
    //以下是有关lazy操作变量 
    int lz;//1:该区间全部变1, 0:该区间全部变0,  -1:无lazy
    bool no;//该区间是否要取反
}tr[MaxN<<2];
int bgn[MaxN],x,y,n,op;
//初始串,修改(询问)区间,总区间长度,运算符 
int maxx(int aa,int bb,int cc){return aa>bb?(aa>cc?aa:cc):(bb>cc?bb:cc);}
//最短三者比较代码^w^ 
tree merge(tree a,tree b){
    tree c;
    c.lz=-1;
    c.no=0;
    c.sum=a.sum+b.sum;
    c.s1=maxx(a.s1,b.s1,a.r1+b.l1); 
    c.s0=maxx(a.s0,b.s0,a.r0+b.l0); 
    if(a.l1){
        c.l1=(a.sum==a.l1?(a.l1+b.l1):(a.l1));
        c.l0=0;
    }
    else {
        c.l0=(a.sum?(a.l0):(a.l0+b.l0));
        c.l1=0;
    }
    if(b.r1){
        c.r1=(b.sum==b.r1?(b.r1+a.r1):(b.r1));
        c.r0=0;
    }
    else {
        c.r0=(b.sum?(b.r0):(b.r0+a.r0)); 
        c.r1=0;
    }
    return c;
}
void tn1(int k,int l,int r){
    tr[k].lz=1;
    tr[k].no=0;
    tr[k].s0=tr[k].l0=tr[k].r0=0;
    tr[k].s1=tr[k].l1=tr[k].r1=tr[k].sum=r-l+1;
}
void tn0(int k,int l,int r){
    tr[k].lz=0;
    tr[k].no=0;
    tr[k].s0=tr[k].l0=tr[k].r0=r-l+1;
    tr[k].s1=tr[k].l1=tr[k].r1=tr[k].sum=0;
}
void no(int k,int l,int r){
    tr[k].no=!tr[k].no;
    swap(tr[k].l0,tr[k].l1);
    swap(tr[k].r0,tr[k].r1);
    swap(tr[k].s0,tr[k].s1);
    tr[k].sum=r-l+1-tr[k].sum;
}
void maintain(int k,int l,int r){
    fangbian;
    if(tr[k].lz==1){
        tn1(ls,l,m);
        tn1(rs,m+1,r);
    }
    if(tr[k].lz==0){
        tn0(ls,l,m);
        tn0(rs,m+1,r);
    }
    if(tr[k].no==1){
        no(ls,l,m);
        no(rs,m+1,r);
    }
    tr[k]=merge(tr[ls],tr[rs]); 
    tr[k].no=0;
    tr[k].lz=-1;
}
void build(int k,int l,int r){
    tr[k].lz=-1;
    if(l==r){
        tr[k].l1=tr[k].r1=tr[k].sum=tr[k].s1=bgn[l];
        tr[k].l0=tr[k].r0=tr[k].s0=!bgn[l];
        return;
    }
    fangbian;
    build(ls,l,m);
    build(rs,m+1,r);
    tr[k]=merge(tr[ls],tr[rs]);
}
void mdf(int k,int l,int r){
    if(x<=l && r<=y){
        if(op==2)no(k,l,r);
        else if(op==1)tn1(k,l,r);
        else if(op==0)tn0(k,l,r);
        return;
    }
    fangbian;
    maintain(k,l,r);
    //往下找 
    if(x<=m)mdf(ls,l,m);
    if(m<y)mdf(rs,m+1,r);
    tr[k]=merge(tr[ls],tr[rs]);
}
tree query(int k,int l,int r){//区间查找 
    if(x<=l && r<=y)return tr[k];//找到区间,返回该区间 
    fangbian;
    maintain(k,l,r);
    //不分叉的情况 
    if(m<x)return query(rs,m+1,r);
    else if(y<=m)return query(ls,l,m);
    //分叉的情况 
    tree L=query(ls,l,m);//该分叉中的左半区间 
    tree R=query(rs,m+1,r);//该分叉中的右半区间 
    tree midd=merge(L,R);
    //if(op==4)cout<<midd.s1<<endl;
    //else if(op==3)cout<<midd.sum<<endl;
    return midd;
}
int main(){
    //freopen("drc.out","w",stdout);
    int m;
    cin>>n>>m;
    for(int i=1; i<=n; i++)cin>>bgn[i];
    build(1,1,n);
    int tot=m;
    while(m--){
        cin>>op>>x>>y;
        x++;y++;
        if(op<3)mdf(1,1,n),tot--;
        else if(op==3)cout<<query(1,1,n).sum<<endl;
        else cout<<query(1,1,n).s1<<endl;
    }
}

写那么多注释目的就是让人看懂。

感谢,连续切了好久了


by qwerty0862 @ 2019-10-06 13:44:52

tql%%%


by 只以 @ 2019-10-06 13:45:34

%%%


by Smile_Cindy @ 2019-10-06 13:47:23

洛谷用户的钓鱼水平有长进啊。


by CBW2007 @ 2019-10-06 13:47:44

编译那么多warning,看起来是运算优先级的问题


by pjykk @ 2019-10-06 13:52:55

洛谷用户的钓鱼水平有所长进啊。


by OωO @ 2019-10-06 13:53:03

洛谷用户的钓鱼水平有长进


by Seg_Tree @ 2019-10-06 13:57:13

@CBW2007 不是,用fangbian来定义变量,这玩意我基本所有线段树都套过了,没错的。你可以仔细看一看我的define。我高度怀疑应该是我的s1出了问题。废话


by CBW2007 @ 2019-10-06 14:03:33

@Lord_Vader 我的意思是后面的语句:

如,m=l+r>>1,有可能理解为先r>>1在加l?


by CBW2007 @ 2019-10-06 14:03:45

在->再


by zrz_orz @ 2019-10-06 14:06:10

@CBW2007 位运算优先级低


| 下一页