HDU3397(Sequence operation)线段树的多种操作
[cpp]/**********************************************题目大意:0 a b将区间[a,b]所有数全部变成01 a b将区间[a,b]所有数全部变成12 a b将区间[a,b]中所有数0 1互换,0变1,1变03 a b输出区间[a,b]中1的个数4 a b输出区间[a,b]中最长连续1的个数算法分析:涉及到线段树的多种操作;0,1两种操作可以合并到一起写;0,1互换即线段树的异或操作;查询区间最长连续1个数的过程中;maxl=[l,m]上最长连续1个数;maxl=[m+1,r]上最长连续1的个数;maxm=min(m-l+1,左孩子的rs)+min(r-m,右孩子的ls);结果应该是这三个中的最大值,即max(maxl,maxr,maxm);其中查询操作和pku3667类似;***********************************************/#include<iostream>#include<cstring>#include<cstdlib>#include<cstdio>#include<climits>#include<algorithm>using namespace std;#define L l,m,u<<1#define R m+1,r,u<<1|1const int N =100010;struct node{int l,r;int ls,ms,rs;//ls左边最长连续1数量;ms:最长连续1数量;rs:右边最长连续1数量;int flag;//01状态int total;//区间1的总数} t[N*3];int len(int u){return t[u].r-t[u].l+1;}int mid(int u){return (t[u].l+t[u].r)>>1;}void PushUp(int u,int x)//把当前结点的信息更新到父结点{t[u].ls=t[u].ms=t[u].rs=t[u].total=x*(t[u].r-t[u].l+1);t[u].flag=x;}void build(int l,int r,int u)//建树{t[u].l=l;t[u].r=r;t[u].ls=t[u].rs=t[u].ms=t[u].total=t[u].flag=0;if(l==r)return;int m=mid(u);build(L);build(R);}void PushUp(int u)//把当前结点的信息更新到父结点{t[u].flag=(t[u<<1].flag==t[u<<1|1].flag?t[u<<1].flag:-1);//更新状态t[u].ls=t[u<<1].ls+((t[u<<1].ls==len(u<<1))?t[u<<1|1].ls:0);//更新左t[u].rs=t[u<<1|1].rs+((t[u<<1|1].rs==len(u<<1|1))?t[u<<1].rs:0);//更新右t[u].ms=max(t[u<<1].rs+t[u<<1|1].ls,max(t[u<<1].ms,t[u<<1|1].ms));//更新整体t[u].total=t[u<<1].total+t[u<<1|1].total;//更新1的总数}void update(int l,int r,int u,int x)//更新区间[l,r]0、1状态{if(t[u].flag==x)return;if(t[u].l==l&&t[u].r==r){PushUp(u,x);return;}if(t[u].flag>=0){PushUp(u<<1,t[u].flag);PushUp(u<<1|1,t[u].flag);t[u].flag=-1;}int m=mid(u);if(r<=m){update(l,r,u<<1,x);}else if(l>m){update(l,r,u<<1|1,x);}else{update(L,x);update(R,x);}PushUp(u);}void swap(int l,int r,int u)//[l,r]0、1交换{if(t[u].l>=l&&t[u].r<=r&&(t[u].flag==0||t[u].flag==1)){int x=t[u].flag^1;PushUp(u,x);return;}if(t[u].flag>=0){PushUp(u<<1,t[u].flag);PushUp(u<<1|1,t[u].flag);}int m=mid(u);if(r<=m){swap(l,r,u<<1);}else if(l>m){swap(l,r,u<<1|1);}else{swap(L);swap(R);}PushUp(u);}int find1(int l,int r,int u)//找区间[l,r]内的1的个数{if(t[u].l==l&&t[u].r==r){return t[u].total;}if(t[u].flag>=0){PushUp(u<<1,t[u].flag);PushUp(u<<1|1,t[u].flag);}int m=mid(u);if(r<=m){return find1(l,r,u<<1);}else if(l>m){return find1(l,r,u<<1|1);}else{return find1(L)+find1(R);}}int find2(int l,int r,int u)//找区间[l,r]内最长连续1的个数{if(t[u].l==l&&t[u].r==r){ 补充:软件开发 , C++ ,
上一个:GCC扩展符(#,##)
下一个:结构体数组计算
- 更多C/C++疑问解答:
- 关于c++的cout输出的问题。
- 在学校里学过C和C++,不过学的很一般,现在自学C#,会不会很难?
- 全国计算机二级C语言笔试题
- 已知某树有2个2度结点,3个3度结点,4个4度结点,问有几个叶子结点?
- c++数据结构内部排序问题,整数排序
- 2012九月计算机二级C语言全国题库,,急求急求
- 如果assert只有一个字符串作为参数,是什么意思呢?
- C语言中,哪些运算符具有左结合性,哪些具有右结合性,帮忙总结下,谢谢了!
- 为什么用结构体编写的程序输入是,0输不出来啊~~~
- 将IEEE—754的十六进制转化为十进制浮点类型,用C或C++都行,多谢各位大侠啊,非常感谢!
- 为什么这个程序求不出公式?
- 这个链表倒置的算法请大家分析下
- c语言函数库调用
- C语言unsigned int纠错
- C语言快排求解啊