题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3397

题目描述:

题目大意:给我们一串二进制串,需要我们对其进行以下操作:

1、输入0,a,b,将a,b范围内的所有二进制数字变为0;

2、输入1,a,b,将a,b范围内的所有二进制数字变为1;

3、输入2,a,b,将a,b范围内的所有二进制数字0变为1,1变为0;

4、输入3,a,b,统计a,b范围内的二进制数字1的个数并输出;

4、输入4,a,b,统计a,b范围内的最长连续的1个数并输出;

代码实现:

#include <cstdio>
#include <algorithm>
using namespace std;
const int MAXN =1e6;
int N,M;
struct node{
/**val记录 0,1操作——赋值
初始值为-1;
val=0表示将当前节点(x)范围内的值全部赋值为0
val=1表示将当前节点(x)范围内的值全部赋值为1 flag记录2操作 ——转换
默认值为0;
flag=1表示将当前节点(x)范围内的0全部转换为1,1全部转换为0 lmax_0记录x范围内从左开始连续的0的长度
rmax_0记录x范围内从右开始连续的0的长度
max_0记录x范围内最长连续的0的长度
sum_0记录x范围内0的个数
同理,lmax_1,rmax_1,max_1,sum_1是用来记录1的*/
int l,r,val,flag;
int lmax_0,rmax_0,max_0,sum_0;
int lmax_1,rmax_1,max_1,sum_1;
int len(){return r-l+;}//记录每个节点区间的总长度
int mid(){return (r+l)/;} void change(int a,int rev){
if(a==){//0操作
lmax_0=rmax_0=max_0=sum_0=len();
lmax_1=rmax_1=max_1=sum_1=;
val=a;flag=;
}else if(a==){//1操作
lmax_0=rmax_0=max_0=sum_0=;
lmax_1=rmax_1=max_1=sum_1=len();
val=a;flag=;
}
if(rev){//如果rev=1,执行2操作
swap(lmax_0,lmax_1);swap(rmax_0,rmax_1);
swap(max_0,max_1);swap(sum_0,sum_1);
flag^=;//即flag由0变为1
}
}
}tree[MAXN*];
int a[MAXN];
///push_up(tree[1],tree[2],tree[3]);
void push_up(node &a,node &b,node &c){
//更新x节点的lmax_0、rmax_0、max_0、sum_0
//以及x节点的lmax_1、rmax_1、max_1、sum_1
a.lmax_0=b.lmax_0;a.rmax_0=c.rmax_0;//父亲的左边最长0串=左子树的左边最长0串,父亲的右边最长0串=右子树的右边最长0串
a.lmax_1=b.lmax_1;a.rmax_1=c.rmax_1;
a.sum_0=b.sum_0+c.sum_0; a.sum_1=b.sum_1+c.sum_1;//父亲总的0的个数=左子树0的个数+右子树0的个数,父亲总的1的个数=左子树1的个数+右子树1的个数
a.max_0=max(max(b.max_0,c.max_0),(b.rmax_0+c.lmax_0));///如果出现像0000001011这种情况,a.max_0的值就应该为b.rmax_0+c.lmax_0
a.max_1=max(max(b.max_1,c.max_1),(b.rmax_1+c.lmax_1));
if(b.len()==b.lmax_0) a.lmax_0+=c.lmax_0;///比如像0000011011这种情况,注意a.lmax_0在刚开始就已经赋值为b.lmax_0了,这只是再次判断以防万一
if(b.len()==b.lmax_1) a.lmax_1+=c.lmax_1;
if(c.len()==c.rmax_0) a.rmax_0+=b.rmax_0;
if(c.len()==c.rmax_1) a.rmax_1+=b.rmax_1;
}
///build(1,0,N-1);//第一个节点的区间的左右的值分别为0,N-1
void build(int x,int l,int r){
tree[x].l=l;tree[x].r=r;
tree[x].lmax_0=tree[x].rmax_0=;
tree[x].lmax_1=tree[x].rmax_1=;
tree[x].max_0=tree[x].max_1=;
tree[x].sum_0=tree[x].sum_1=;
tree[x].flag=;tree[x].val=-;
if(l==r){
tree[x].change(a[l],);
return ;
}
int mid=(l+r)/;
build(x<<,l,mid);
build(x<<|,mid+,r);
push_up(tree[x],tree[x<<],tree[x<<|]);
}
///if(a==0||a==1||a==2) update(1,b,c,a);
/*
0用于将范围内所有的数变为0,1用于将范围内所有的数变为1,2用于将范围内所有的0变为1,1变为0
*/
void update(int x,int l,int r,int val){
int L=tree[x].l,R=tree[x].r;
if(l<=L && R<=r){///[L,R]包含于[l,r]
if(val==||val==) tree[x].change(val,);//这一步即能实现将值进行转换
else tree[x].change(-,);//这一步实现2操作
return ;
}
//push_down的作用,实现向下更新
if(tree[x].val!=-||tree[x].flag)//仅针对于刚刚更新的节点来说,即上方代码实现将当前节点与该节点以上的节点更新后,
//接下来的节点tree[x].val已经改变了,所以需要对其左右子区间进行更新
{
tree[x<<].change(tree[x].val,tree[x].flag);
tree[x<<|].change(tree[x].val,tree[x].flag);
tree[x].val=-;tree[x].flag=;
}
int mid=(L+R)/;
///如果mid直接处在l的右边就只更新左区间(条件1),处在r的左边就只更新右区间(条件2),如mid处在[l,r]之间,需要更新左右区间(条件1+2)
if(mid>=l)
update(x<<,l,r,val);
if(mid<r)
update(x<<|,l,r,val);
push_up(tree[x],tree[x<<],tree[x<<|]);
} int query(int x,int l,int r,int val)
{
int L=tree[x].l,R=tree[x].r;
if(l<=L && R<=r)
{
if(val==) return tree[x].sum_1;
else return tree[x].max_1;
}
int mid=(L+R)/;
//push_down的作用,实现向下更新
if(tree[x].val!=-||tree[x].flag)
{
tree[x<<].change(tree[x].val,tree[x].flag);
tree[x<<|].change(tree[x].val,tree[x].flag);
tree[x].val=-;tree[x].flag=;
}
if(r<=mid)
return query(x<<,l,r,val);
else if(l>mid)
return query(x<<|,l,r,val);
else
{
int max1=query(x<<,l,r,val);
int max2=query(x<<|,l,r,val);
if(val==)
return max1+max2;
int max3=min(tree[x<<].r-l+,tree[x<<].rmax_1)+min(r-tree[x<<|].l+,tree[x<<|].lmax_1);
return max(max(max1,max2),max3);
}
} int main(){
int T;scanf("%d",&T);
while(T--){
scanf("%d%d",&N,&M);
for(int i=;i<N;i++)
scanf("%d",&a[i]);
build(,,N-);
while(M--){
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
if(a==||a==||a==) update(,b,c,a);
else printf("%d\n",query(,b,c,a));//如果a等于3,输出[b,c]之间1的个数,a=4输出[b,c]之间最长连续1的个数
}
}
return ;
}4

线段树-hdu3397的更多相关文章

  1. hdu3397 线段树 成段更新

    这题真的呵呵了.敲了很长时间,调了很多bug,把0 1 输出,解决了.最后想取反,怎么搞都有bug, 最后还是看了大牛们的博客.不过这题真的敲得爽,调bug时基本把线段树过程全部弄了一遍. #incl ...

  2. hdu-3397 Sequence operation 线段树多种标记

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=3397 题目大意: 0 a b表示a-b区间置为0 1 a b表示a-b区间置为1 2 a b表示a- ...

  3. 线段树总结 (转载 里面有扫描线类 还有NotOnlySuccess线段树大神的地址)

    转载自:http://blog.csdn.net/shiqi_614/article/details/8228102 之前做了些线段树相关的题目,开学一段时间后,想着把它整理下,完成了大牛NotOnl ...

  4. [转载]完全版线段树 by notonlysuccess大牛

    原文出处:http://www.notonlysuccess.com/ (好像现在这个博客已经挂掉了,在网上找到的全部都是转载) 今天在清北学堂听课,听到了一些很令人吃惊的消息.至于这消息具体是啥,等 ...

  5. 【转】线段树完全版~by NotOnlySuccess

    线段树完全版  ~by NotOnlySuccess 很早前写的那篇线段树专辑至今一直是本博客阅读点击量最大的一片文章,当时觉得挺自豪的,还去pku打广告,但是现在我自己都不太好意思去看那篇文章了,觉 ...

  6. 《完全版线段树》——notonlysuccess

    转载自:NotOnlySuccess的博客 [完全版]线段树 很早前写的那篇线段树专辑至今一直是本博客阅读点击量最大的一片文章,当时觉得挺自豪的,还去pku打广告,但是现在我自己都不太好意思去看那篇文 ...

  7. 【转】 线段树完全版 ~by NotOnlySuccess

    载自:NotOnlySuccess的博客 [完全版]线段树 很早前写的那篇线段树专辑至今一直是本博客阅读点击量最大的一片文章,当时觉得挺自豪的,还去pku打广告,但是现在我自己都不太好意思去看那篇文章 ...

  8. 【转载】完全版线段树 by notonlysuccess大牛

    原文出处:http://www.notonlysuccess.com/ 今晚上比赛就考到了 排兵布阵啊,难受. [完全版]线段树 很早前写的那篇线段树专辑至今一直是本博客阅读点击量最大的一片文章,当时 ...

  9. bzoj3932--可持久化线段树

    题目大意: 最近实验室正在为其管理的超级计算机编制一套任务管理系统,而你被安排完成其中的查询部分.超级计算机中的 任务用三元组(Si,Ei,Pi)描述,(Si,Ei,Pi)表示任务从第Si秒开始,在第 ...

随机推荐

  1. swift 实践- 02 -- 自定义cell 的简单使用

    import UIKit class MyTableViewCell: UITableViewCell { var imageV: UIImageView? var titleLabel: UILab ...

  2. Ubuntu16.04配置Tomcat的80端口访问

    [问题描述] 在阿里云 ECS 服务器 Ubuntu16.04 下部署 Java Web 应用时,发现配置的 Tomcat 服务启动后 80 端口无法被监听. [问题原因] 出现该问题的主要原因是:非 ...

  3. Confluence 6 已经存在的 Confluence 安装配置一个数据源连接

    如果你希望在使用 JDBC 直接方式的应用中切换到使用数据源: 停止 Confluence. 备份下面的文件,以防止你可能需要重新恢复你的配置: <installation-directory& ...

  4. Confluence 6 PostgreSQL 输入你的数据库细节

    在 Confluence 的设置安装向导中,将会指导你 Confluence 如何连接到你的数据库.请确定选择 "My own database". 使用 JDBC 连接(默认) ...

  5. Confluence 6 升级自定义的站点和空间关闭缓存

    Velocity 被配置在内存中使用缓存模板.当你在 Confluence 中编辑了页面的模板文件,Confluence 知道文件进行了编辑,将会重新从磁盘中载入模板文件.如果你直接在 Conflue ...

  6. C++ 解析Json——jsoncpp(转)

    原文:https://www.cnblogs.com/liaocheng/p/4243731.html JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式,和 ...

  7. Allegro PCB Design GXL (legacy) 将指定的层导出为DXF

    Allegro PCB Design GXL (legacy) version 16.6-2015 1.菜单:Display > Color/Visibility... 2.打开Color Di ...

  8. Django Web开发基础环境配置流程

    创建虚拟环境 mkvirtualenv django_py3_1.11 -p python3 注意需要联网 安装Django 使用django 1.11.11版本,注意需要联网 pip install ...

  9. 51 Nod 1256 乘法逆元(数论:拓展欧几里得)

    1256 乘法逆元  基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题  收藏  关注 给出2个数M和N(M < N),且M与N互质,找出一个数K满足0 < K ...

  10. 记录sql server中数据创建时间和最后修改时间,方便查找问题

    getdate()用例: 2008-12-29 16:25:46.635 1.创建时间:将字段设置为datetime类型,并设置默认值为 getdate() 2.修改时间:通过触发器,在 update ...