bzoj 1858: [Scoi2010]序列操作
来源:互联网 发布:js淘宝购物车脚本之家 编辑:程序博客网 时间:2024/04/30 20:21
bzoj 1858: [Scoi2010]序列操作
线段树
题意
给一个01串,设计数据结构,支持5种操作:
- 区间置零
- 区间置一
- 区间翻转,0变1,1变0
- 查询区间1的个数
- 查询区间内最长的连续1的个数
思路
线段树维护连续子区间。就是复杂一点而已。因为有翻转操作,所以要同时维护0和1的信息。
维护区间0、1的个数,区间最长连续0、1,最长前缀0、1,最长后缀0、1。
最好重载+号,pushup就相当于做加法。
代码
#include<cstdio>#include<cstdlib>#include<cstring>#include<algorithm>#include<map>#define lson l,mid,rt<<1#define rson mid+1,r,rt<<1|1#define M(a,b) memset(a,b,sizeof(a))using namespace std;const int MAXN=100007;const int oo=0x3f3f3f3f;int max3(int a, int b, int c) { return std::max(std::max(a, b), c); }int num[MAXN];struct Stree{ int flip;//翻转 int num0, num1;//0的个数,1的个数 int set0, set1;//置0,置1 int pre0, pre1;//连续前缀0,连续前缀1 int suf0, suf1;//连续后缀0,连续后缀1 int ma0, ma1;//最长连续0,最长连续1 inline void init() { flip=num0=num1=set0=set1=pre0=pre1=suf0=suf1=ma0=ma1=0; }}stree[MAXN<<2];void pushup(int l, int r, int rt){ stree[rt].num0=stree[rt<<1].num0+stree[rt<<1|1].num0; stree[rt].num1=stree[rt<<1].num1+stree[rt<<1|1].num1; stree[rt].ma0=max3(stree[rt<<1].ma0, stree[rt<<1|1].ma0, stree[rt<<1].suf0+stree[rt<<1|1].pre0); stree[rt].ma1=max3(stree[rt<<1].ma1, stree[rt<<1|1].ma1, stree[rt<<1].suf1+stree[rt<<1|1].pre1); int mid=(l+r)>>1; if(stree[rt<<1].pre0==mid-l+1) stree[rt].pre0=stree[rt<<1].pre0+stree[rt<<1|1].pre0; else stree[rt].pre0=stree[rt<<1].pre0; if(stree[rt<<1].pre1==mid-l+1) stree[rt].pre1=stree[rt<<1].pre1+stree[rt<<1|1].pre1; else stree[rt].pre1=stree[rt<<1].pre1; if(stree[rt<<1|1].suf0==r-mid) stree[rt].suf0=stree[rt<<1].suf0+stree[rt<<1|1].suf0; else stree[rt].suf0=stree[rt<<1|1].suf0; if(stree[rt<<1|1].suf1==r-mid) stree[rt].suf1=stree[rt<<1].suf1+stree[rt<<1|1].suf1; else stree[rt].suf1=stree[rt<<1|1].suf1;}void pushdown(int l, int r, int rt){ int mid=(l+r)>>1; if(stree[rt].set0) { stree[rt].set0=0; stree[rt<<1].flip=stree[rt<<1].set1=0;stree[rt<<1].set0=1; stree[rt<<1].num0=mid-l+1;stree[rt<<1].num1=0; stree[rt<<1].pre0=stree[rt<<1].suf0=stree[rt<<1].ma0=mid-l+1; stree[rt<<1].pre1=stree[rt<<1].suf1=stree[rt<<1].ma1=0; stree[rt<<1|1].flip=stree[rt<<1|1].set1=0;stree[rt<<1|1].set0=1; stree[rt<<1|1].num0=r-mid;stree[rt<<1|1].num1=0; stree[rt<<1|1].pre0=stree[rt<<1|1].suf0=stree[rt<<1|1].ma0=r-mid; stree[rt<<1|1].pre1=stree[rt<<1|1].suf1=stree[rt<<1|1].ma1=0; } else if(stree[rt].set1) { stree[rt].set1=0; stree[rt<<1].flip=stree[rt<<1].set0=0;stree[rt<<1].set1=1; stree[rt<<1].num1=mid-l+1;stree[rt<<1].num0=0; stree[rt<<1].pre1=stree[rt<<1].suf1=stree[rt<<1].ma1=mid-l+1; stree[rt<<1].pre0=stree[rt<<1].suf0=stree[rt<<1].ma0=0; stree[rt<<1|1].flip=stree[rt<<1|1].set0=0;stree[rt<<1|1].set1=1; stree[rt<<1|1].num1=r-mid;stree[rt<<1|1].num0=0; stree[rt<<1|1].pre1=stree[rt<<1|1].suf1=stree[rt<<1|1].ma1=r-mid; stree[rt<<1|1].pre0=stree[rt<<1|1].suf0=stree[rt<<1|1].ma0=0; } else if(stree[rt].flip) { stree[rt].flip=0; stree[rt<<1].flip^=1; if(stree[rt<<1].set0) stree[rt<<1].set1=1, stree[rt<<1].set0=0, stree[rt<<1].flip=0; else if(stree[rt<<1].set1) stree[rt<<1].set0=1, stree[rt<<1].set1=0, stree[rt<<1].flip=0; swap(stree[rt<<1].ma0, stree[rt<<1].ma1); swap(stree[rt<<1].num0, stree[rt<<1].num1); swap(stree[rt<<1].pre0, stree[rt<<1].pre1); swap(stree[rt<<1].suf0, stree[rt<<1].suf1); stree[rt<<1|1].flip^=1; if(stree[rt<<1|1].set0) stree[rt<<1|1].set1=1, stree[rt<<1|1].set0=0, stree[rt<<1|1].flip=0; else if(stree[rt<<1|1].set1) stree[rt<<1|1].set0=1, stree[rt<<1|1].set1=0, stree[rt<<1|1].flip=0; swap(stree[rt<<1|1].ma0, stree[rt<<1|1].ma1); swap(stree[rt<<1|1].num0, stree[rt<<1|1].num1); swap(stree[rt<<1|1].pre0, stree[rt<<1|1].pre1); swap(stree[rt<<1|1].suf0, stree[rt<<1|1].suf1); }}void build(int l, int r, int rt){ stree[rt].init(); if(l==r) { if(num[l]) stree[rt].num1=stree[rt].pre1=stree[rt].suf1=stree[rt].ma1=1; else stree[rt].num0=stree[rt].pre0=stree[rt].suf0=stree[rt].ma0=1; return; } int mid=(l+r)>>1; build(lson), build(rson); pushup(l, r, rt);}void update(int L, int R, int k, int l, int r, int rt){ if(L<=l&&r<=R) { if(k==0)//set0 { if(stree[rt].set0) return; else { stree[rt].set1=stree[rt].flip=0;stree[rt].set0=1; stree[rt].num0=stree[rt].pre0=stree[rt].suf0=stree[rt].ma0=r-l+1; stree[rt].num1=stree[rt].pre1=stree[rt].suf1=stree[rt].ma1=0; } } else if(k==1)//set1 { if(stree[rt].set1) return; else { stree[rt].set0=stree[rt].flip=0;stree[rt].set1=1; stree[rt].num0=stree[rt].pre0=stree[rt].suf0=stree[rt].ma0=0; stree[rt].num1=stree[rt].pre1=stree[rt].suf1=stree[rt].ma1=r-l+1; } } else if(k==2)//flip { if(stree[rt].set0) stree[rt].set0=0, stree[rt].set1=1, stree[rt].flip=0; else if(stree[rt].set1) stree[rt].set0=1, stree[rt].set1=0, stree[rt].flip=0; else stree[rt].flip^=1; swap(stree[rt].ma0, stree[rt].ma1); swap(stree[rt].num0, stree[rt].num1); swap(stree[rt].pre0, stree[rt].pre1); swap(stree[rt].suf0, stree[rt].suf1); } return; } pushdown(l, r, rt); int mid=(l+r)>>1; if(L<=mid) update(L, R, k, lson); if(R>mid) update(L, R, k, rson); pushup(l, r, rt);}int query1(int L, int R, int l, int r, int rt){ if(L<=l&&r<=R) return stree[rt].num1; pushdown(l, r, rt); int mid=(l+r)>>1; int sum=0; if(L<=mid) sum+=query1(L, R, lson); if(mid<R) sum+=query1(L, R, rson); return sum;}Stree query2(int L, int R, int l, int r, int rt){ if(L<=l&&r<=R) return stree[rt]; pushdown(l, r, rt); int mid=(l+r)>>1; Stree ll, rr;ll.init(), rr.init(); if(L<=mid) ll=query2(L, R, lson); if(mid<R) rr=query2(L, R, rson); Stree res;res.init(); res.ma1=max3(ll.ma1, rr.ma1, ll.suf1+rr.pre1); if(ll.pre1==mid-l+1) res.pre1=ll.pre1+rr.pre1; else res.pre1=ll.pre1; if(rr.suf1==r-mid) res.suf1=ll.suf1+rr.suf1; else res.suf1=rr.suf1; return res;}int main(){ int n, m;scanf("%d%d", &n, &m); for(int i=1;i<=n;i++) scanf("%d", &num[i]); build(1, n, 1); for(int i=1;i<=m;i++) { int op, x, y;scanf("%d%d%d", &op, &x, &y);x++, y++; if(op==0) update(x, y, 0, 1, n, 1); else if(op==1) update(x, y, 1, 1, n, 1); else if(op==2) update(x, y, 2, 1, n, 1); else if(op==3) printf("%d\n", query1(x, y, 1, n, 1)); else if(op==4) printf("%d\n", query2(x, y, 1, n, 1).ma1); } //system("pause"); return 0;}
阅读全文
0 0
- 【BZOJ 1858】 [Scoi2010]序列操作
- BZOJ 1858 [Scoi2010]序列操作
- bzoj 1858: [Scoi2010]序列操作
- BZOJ 1858 [Scoi2010]序列操作
- bzoj[Scoi2010]序列操作
- bzoj 1858: [Scoi2010] 序列操作 题解
- BZOJ 1858 SCOI2010 序列操作 线段树
- BZOJ 1858 [Scoi2010]序列操作 线段树
- 【bzoj 1858】 [Scoi2010]序列操作 线段树
- bzoj 1858: [Scoi2010]序列操作 线段树
- BZOJ 1858 [Scoi2010]序列操作 线段树
- BZOJ 1858 [Scoi2010]序列操作 线段树
- BZOJ 1858: [Scoi2010]序列操作 线段树
- BZOJ 1858: [Scoi2010]序列操作 线段树
- 1858: [Scoi2010]序列操作
- 1858: [Scoi2010]序列操作
- 1858: [Scoi2010]序列操作
- bzoj 1858: [Scoi2010]序列操作(线段树)
- 笨办法学 Python · 续 练习 35:解释器
- linux acl 改变特定用户的文件权限
- Helper2416开发板学习①环境搭建
- China Operating System 电脑操作系统 2016全球互联网排名
- sbl.py
- bzoj 1858: [Scoi2010]序列操作
- POJ
- 自己实现telnet程序
- 所有文件夹 目录 详细信息
- 输入子系统驱动模型
- PC机串口调试助手与单片机通信字符问题
- Python(1)--变量及变量的赋值
- Web API 方法的返回类型、格式器、过滤器
- iiiLab视频解析下载网站的几个使用技巧