线段树1(带懒惰标记的区间更新和整棵树的查询)
来源:互联网 发布:c语言经典算法100例 编辑:程序博客网 时间:2024/04/28 17:08
Problem Description
皮特的幸运数是2和5。只由幸运数字2和5组成的数列,称为幸运数列。对于幸运数列,有两种操作。
1、switch i j
表示数列从第i个数到第j个数中,所有的2改成5,所有的5改成2.例如幸运数列25525,执行switch 2 4操作,则数列变成22255
2、count
表示要求输出当前幸运数列的最长不下降子序列(即子序列中后面的数都不小于前面的数)的长度。例如幸运数列252255,其中222,555,2555是它的不下降子序列,而2525不是,可以看出,最长不下降子序列是22255,长度为5。
现在给出一个长度为n的幸运数列,再依次给出m个操作,对于每个count操作,输出当前幸运数列的最长不下降子序列的长度。
Input
输入包含多组数据。(数据不超过10组)
每组数据的第一行有两个整数n,m(n,m<=100000),分别表示数列的长度和操作个数。
接下来一行,有一个长度为n的只由2和5构成的数列。
接下来m行,每行一个操作,是count或者switch i j,含义如题所述
Output
对于每组数据的每个count操作,都输出一行,包含一个整数,表示当前幸运数列的最长不下降子序列的长度。
#include<stdio.h>#include<string.h>#include<algorithm>using namespace std;const int MAXN=100005;struct TREE{int l2,l5,l25,l52;bool flag;}tree[501000];char num[101000];void PushUp(int node){tree[node].l2=tree[node<<1].l2+tree[node<<1|1].l2;tree[node].l5=tree[node<<1].l5+tree[node<<1|1].l5;tree[node].l25=max(tree[node<<1].l25+tree[node<<1|1].l5,tree[node<<1].l2+tree[node<<1|1].l25);tree[node].l52=max(tree[node<<1].l52+tree[node<<1|1].l2,tree[node<<1].l5+tree[node<<1|1].l52);}void Build(int node ,int left,int right){tree[node].flag=false;if(left==right){if(num[left]=='2'){tree[node].l2=1;tree[node].l5=0;tree[node].l25=1;tree[node].l52=1;}else if(num[left]=='5'){tree[node].l2=0;tree[node].l5=1;tree[node].l25=1;tree[node].l52=1;}}else{int mid=(left+right)>>1;Build(node<<1,left,mid);Build(node<<1|1,mid+1,right);PushUp(node);}}void change(int node,int l,int r,int ql,int qr){if(l==r)//一个点,直接改{swap(tree[node].l2,tree[node].l5);swap(tree[node].l25,tree[node].l52);}else if(l==ql&&r==qr)//正好对应线段树上的区间,打懒惰标记,先不修改子树{swap(tree[node].l2,tree[node].l5);swap(tree[node].l25,tree[node].l52);tree[node].flag^=1;}else//在线段树的不同区间内{int mid=l+r>>1;if(tree[node].flag)//解决懒惰标记,向下修改,分两段{change(node<<1,l,mid,l,mid);change(node<<1|1,mid+1,r,mid+1,r);tree[node].flag=false;}if(qr<=mid)change(node<<1,l,mid,ql,qr);//全在左边else if(ql>mid)change(node<<1|1,mid+1,r,ql,qr);//全在右边else//左右都有{change(node<<1,l,mid,ql,mid);change(node<<1|1,mid+1,r,mid+1,qr);}PushUp(node);}}int query(int node,int l,int r){return max(tree[node].l25,max(tree[node].l2,tree[node].l5));}int main(){int n,m,i,l,r;char ope[10];while(scanf("%d %d",&n,&m)!=EOF){memset(tree,0,sizeof(tree));scanf("%s",num+1);//printf("%s",num+1);Build(1,1,n);for(i=0;i<m;i++){scanf("%s",ope);if(ope[0]=='s'){scanf("%d %d",&l,&r);change(1,1,n,l,r);}else if(ope[0]=='c'){printf("%d\n",query(1,1,n));}}}return 0;}
0 0
- 线段树1(带懒惰标记的区间更新和整棵树的查询)
- hdu 1556 Color the ball(线段树区间更新单点查询+懒惰标记)
- hdu1698 Just a Hook (线段树区间更新 懒惰标记)
- NEFU 1111 线段树区间更新+懒惰标记
- HDU1698 线段树+区间更新+懒惰标记-Just a Hook
- [线段树]poj3667 Hotel(区间合并、更新、延迟/懒惰标记
- hdu1698 Just a Hook(线段树 区间更新+懒惰标记)
- 线段树区间修改 懒惰标记 维护和、最大值、最小值
- poj3468---线段树----区间单点更新、区间和查询----有延迟标记
- hdu 1698 Just a Hook (线段树区间更新+懒惰标记)
- zoj 2706 Thermal Death of the Universe(线段树区间更新+懒惰标记)
- 线段树学习笔记(单点更新+区间查询最大值+lazy标记+pushdown操作+区间更新+求区间和)
- 树的区间查询与更新(线段树)
- 区间更新 区间和查询 带有延迟标记 线段树 hdu1698; 附:csa 区间加值,维护最大值
- nyoj116 士兵杀敌(二)(线段树的区间查询和单点更新)
- POJ 3468 线段树 区间操作 懒惰标记
- hdu 3397 线段树+区间合并+懒惰标记 好题
- [模板]线段树的建树、查询、单点更新、区间更新
- 并查集算法-动态连通性
- 如何学习计算机图形学
- UVa 11419 二分图最小点覆盖 续写 好题
- HashSet集合
- android 源码名称及路径
- 线段树1(带懒惰标记的区间更新和整棵树的查询)
- C 内核空间和用户空间中段错误
- C++Primer(5th)学习-数组篇
- 欢迎使用CSDN-markdown编辑器
- JavaScriptCore使用
- Android 中 activity 窗口模式的实现
- linux虚拟机VMware vSphere上安装VMware Tools
- Gym 101028E-Teams-求一组数的最大公约数
- 断点续传续播的大概原理