bzoj1858序列操作 线段树
来源:互联网 发布:重装ubuntu系统分区 编辑:程序博客网 时间:2024/05/17 01:56
题目大意:01序列 可覆盖取反查询区间最长连续1 区间1的个数
BZOJ1858序列操作
记录多个信息 maxlen需要技巧 #滑稽
#include<iostream>#include<cstdio>#include<cstring>#define N 100005using namespace std;struct Seg {int l,r,mx[2],ln[2],rn[2],sum[2],cov,rev;}t[N*4];int a[N],n,m;Seg merge(Seg a,Seg b){ if(a.rev==-1) return b; if(b.rev==-1) return a; Seg tmp; tmp.l=a.l;tmp.r=b.r; tmp.cov=-1;tmp.rev=0; for(int i=0;i<=1;i++){ tmp.ln[i]=a.ln[i]==(a.r-a.l+1)?a.ln[i]+b.ln[i]:a.ln[i]; tmp.rn[i]=b.rn[i]==(b.r-b.l+1)?b.rn[i]+a.rn[i]:b.rn[i]; tmp.mx[i]=max(a.mx[i],b.mx[i]); if(a.rn[i] && b.ln[i]) tmp.mx[i]=max(a.rn[i]+b.ln[i],tmp.mx[i]); tmp.sum[i]=a.sum[i]+b.sum[i]; } return tmp;}void newcover(int k){ int r=t[k].r,l=t[k].l; t[k].ln[0]=t[k].rn[0]=t[k].sum[0]=t[k].mx[0]=t[k].cov==0?(r-l+1):0; t[k].ln[1]=t[k].rn[1]=t[k].sum[1]=t[k].mx[1]=t[k].cov==1?(r-l+1):0;}void newrev(int k){ swap(t[k].ln[0],t[k].ln[1]); swap(t[k].rn[0],t[k].rn[1]); swap(t[k].sum[0],t[k].sum[1]); swap(t[k].mx[0],t[k].mx[1]);}void pushup(int k){ t[k]=merge(t[k<<1],t[k<<1|1]);}void pushdown(int k){ if(t[k].cov!=-1) { t[k<<1].cov=t[k<<1|1].cov=t[k].cov;t[k].cov=-1; t[k<<1].rev=0;t[k<<1|1].rev=0; newcover(k<<1);newcover(k<<1|1);return; } if(t[k].rev==1){ if(t[k<<1].cov!=-1) t[k<<1].cov^=1; else t[k<<1].rev^=t[k].rev; if(t[k<<1|1].cov!=-1) t[k<<1|1].cov^=1; else t[k<<1|1].rev^=t[k].rev; t[k].rev=0; newrev(k<<1);newrev(k<<1|1);return; }}void build(int k,int l,int r){ if(l==r){ t[k].l=t[k].r=l;t[k].cov=a[l];t[k].rev=0; newcover(k);return; } int mid=(l+r)>>1; build(k<<1,l,mid);build(k<<1|1,mid+1,r); pushup(k);}void cover(int k,int a,int b,int x){ int l=t[k].l,r=t[k].r; if(b<l || r<a) return; if(a<=l && r<=b){ t[k].rev=0;t[k].cov=x; newcover(k);return; } pushdown(k); cover(k<<1,a,b,x);cover(k<<1|1,a,b,x); pushup(k);}void rev(int k,int a,int b){ int l=t[k].l,r=t[k].r; if(b<l || r<a) return; if(a<=l && r<=b){ if(t[k].cov!=-1) t[k].cov^=1,newcover(k); else t[k].rev^=1,newrev(k);return; } pushdown(k); rev(k<<1,a,b);rev(k<<1|1,a,b); pushup(k);}int asksum(int k,int a,int b){ int l=t[k].l,r=t[k].r; if(b<l || r<a) return 0; if(a<=l && r<=b) return t[k].sum[1]; pushdown(k); return asksum(k<<1,a,b)+asksum(k<<1|1,a,b);}Seg asklen(int k,int a,int b){ int l=t[k].l,r=t[k].r; if(b<l || r<a) return t[0]; if(a<=l && r<=b) return t[k]; pushdown(k); return merge(asklen(k<<1,a,b),asklen(k<<1|1,a,b));}int main(){ freopen("in.txt","r",stdin); freopen("out.txt","w",stdout); scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%d",&a[i]); build(1,1,n);t[0].rev=-1; for(int i=1;i<=m;i++){ int opt,a,b; scanf("%d%d%d",&opt,&a,&b);a++;b++; if(opt==0) cover(1,a,b,0); if(opt==1) cover(1,a,b,1); if(opt==2) rev(1,a,b); if(opt==3) printf("%d\n",asksum(1,a,b)); if(opt==4) printf("%d\n",asklen(1,a,b).mx[1]); } return 0;}
0 0
- bzoj1858序列操作 线段树
- 【BZOJ1858】[Scoi2010]序列操作 线段树
- [BZOJ1858]SCOI2010序列操作|线段树
- bzoj1858 序列操作 线段树打标记
- 【codevs2421】【BZOJ1858】序列操作,线段树
- 【BZOJ1858】[Scoi2010]序列操作【线段树】
- BZOJ1858 序列操作 (线段树)
- 【BZOJ1858】序列操作(SCOI2010)-线段树
- [省选] [线段树] [BZOJ1858] [SCOI2010] 序列操作
- 线段树 BZOJ1858 [Scoi2010]序列操作
- bzoj1858:序列操作 (线段树区间信息合并)
- 线段树——BZOJ1858/Luogu2572 [SCOI2010]序列操作
- hdu3397 Sequence operation 线段树区间更新&&bzoj1858: [Scoi2010]序列操作
- bzoj1858【scoi2010】序列操作
- [BZOJ1858] [Scoi2010]序列操作
- bzoj1858: [Scoi2010]序列操作
- BZOJ1858 [Scoi2010]序列操作
- BZOJ1858: [Scoi2010]序列操作
- javaDoc和java文件的注释以及javadoc生成出现的问题【dos option选项】
- php程序员应该掌握的10个技能
- nload - displays the current network usage
- POJ1067 取石子游戏
- 有项目时认真搞项目,没项目时认真搞平台。
- bzoj1858序列操作 线段树
- QUST第七届省选-装修
- 第三步:kafka的server启动过程 源代码运行内幕机制
- [BZOJ1660][Usaco2006 Nov]Bad Hair Day 乱发节(单调栈)
- 用小猫统计制作运动员评价管理系统:制作从表与制作主表有一点不同,需要选择创建关联字段
- Android官方文档之App Components(Activities)
- gcc编译基本用法
- Spring基础-上-概念篇
- 用小猫统计制作运动员评价管理系统:设置主从表关联