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 位运算优先级低