hdu3397 线段树 成段更新
这题真的呵呵了。敲了很长时间,调了很多bug,把0 1 输出,解决了。最后想取反,怎么搞都有bug,
最后还是看了大牛们的博客。不过这题真的敲得爽,调bug时基本把线段树过程全部弄了一遍。
#include<stdio.h>
#include<string.h>
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define maxn 100010
int mark[maxn<<];//成端更新用
int rsum[maxn<<],lsum[maxn<<],msum[maxn<<];//来计算连续的最多的1
int numone[maxn<<];//不连续区间1的个数
int num[maxn<<];//输入数组
int max(int x,int y)
{
return x>y?x:y;
}
int min(int x,int y)
{
return x<y?x:y;
} void pushup(int l,int r,int rt)
{
int len=r-l+;
int m=(l+r)/;
if(mark[rt<<]==mark[rt<<|])
mark[rt]=mark[rt<<];//向上更新维护mark
else mark[rt]=-; if(mark[rt]==)
{
msum[rt]=lsum[rt]=rsum[rt]=numone[rt]=len;//如果mark为1,表明全要为一
}
else if(mark[rt]==)
{
numone[rt]=lsum[rt]=msum[rt]=rsum[rt]=;//类似
}
else//如果mark为-1
{
lsum[rt]=lsum[rt<<];
rsum[rt]=rsum[rt<<|];
msum[rt]=max(msum[rt<<],msum[rt<<|]);
numone[rt]=numone[rt<<]+numone[rt<<|];
if(lsum[rt<<]==m-l+)lsum[rt]=lsum[rt<<]+lsum[rt<<|];
if(rsum[rt<<|]==r-m)rsum[rt]=rsum[rt<<|]+rsum[rt<<];
msum[rt]=max(msum[rt],lsum[rt<<|]+rsum[rt<<]);
}
} void pushdown(int l,int r,int rt)
{ if(mark[rt]!=-)
{
mark[rt<<]=mark[rt<<|]=mark[rt];
if(mark[rt]==)
{
int len=r-l+;
numone[rt<<]=lsum[rt<<]=rsum[rt<<]=msum[rt<<]=len-len/;
numone[rt<<|]=lsum[rt<<|]=rsum[rt<<|]=msum[rt<<|]=len/;
}
else
{
lsum[rt<<]=rsum[rt<<]=msum[rt<<]=numone[rt<<]=;
lsum[rt<<|]=rsum[rt<<|]=msum[rt<<|]=numone[rt<<|]=;
}
mark[rt]=-;
}
} void build(int l,int r,int rt)
{
if(l==r)
{
numone[rt]=lsum[rt]=rsum[rt]=msum[rt]=mark[rt]=num[l];
return;
}
int m=(l+r)/;
build(lson);
build(rson);
pushup(l,r,rt);
}
void updata(int L,int R,int c,int l,int r,int rt)//更新0 和 1的情况
{
if(l>=L&&R>=r)
{
mark[rt]=c;
if(c==)
{
lsum[rt]=rsum[rt]=msum[rt]=;
numone[rt]=;
}
else if(c==)
{
lsum[rt]=rsum[rt]=msum[rt]=r-l+;
numone[rt]=r-l+;
}
return ;
}
pushdown(l,r,rt);
int m=(l+r)/;
if(m>=L)
updata(L,R,c,lson);
if(R>m)
updata(L,R,c,rson);
pushup(l,r,rt);
} void change(int L,int R,int l,int r,int rt)//取反
{
if(l>=L&&R>=r&&mark[rt]!=-)
{
if(mark[rt]==)
lsum[rt]=msum[rt]=rsum[rt]=numone[rt]=;
else if(mark[rt]==)
lsum[rt]=msum[rt]=rsum[rt]=numone[rt]=r-l+;
mark[rt]^=;
return;
}
pushdown(l,r,rt);
int m=(l+r)/;
if(m>=L)
change(L,R,lson);
if(R>m)
change(L,R,rson);
pushup(l,r,rt);
} int query(int L,int R,int l,int r,int rt)//查询1的个数
{
if(l>=L&&R>=r)
{
return numone[rt];
}
pushdown(l,r,rt);
int ret=;
int m=(l+r)/;
if(m>=L)
ret+=query(L,R,lson);
if(R>m)
ret+=query(L,R,rson);
return ret;
} int queryone(int L,int R,int l,int r,int rt)//查询连续的1长
{
if(L<=l&&R>=r)
{
return msum[rt];
}
pushdown(l,r,rt);
int ret=-;
int m=(l+r)/;
if(m>=L)
ret=max(ret,queryone(L,R,lson));
if(R>m)
ret=max(ret,queryone(L,R,rson));
ret=max(ret,min(m-L+,rsum[rt<<])+min(R-m,lsum[rt<<|]));//长度是否合法
return ret;
} int main()
{
int i,n,m,t;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m); for(i=;i<=n;i++)
scanf("%d",&num[i]); build(,n,);
int x,y,z; while(m--)
{
scanf("%d%d%d",&x,&y,&z);
if(x==)
updata(y+,z+,,,n,);
else if(x==)
updata(y+,z+,,,n,);
else if(x==)
change(y+,z+,,n,);
else if(x==)
printf("%d\n",query(y+,z+,,n,));
else if(x==)
printf("%d\n",queryone(y+,z+,,n,));
}
}
}
hdu3397 线段树 成段更新的更多相关文章
- ACM: Copying Data 线段树-成段更新-解题报告
Copying Data Time Limit:2000MS Memory Limit:262144KB 64bit IO Format:%I64d & %I64u Description W ...
- Codeforces Round #149 (Div. 2) E. XOR on Segment (线段树成段更新+二进制)
题目链接:http://codeforces.com/problemset/problem/242/E 给你n个数,m个操作,操作1是查询l到r之间的和,操作2是将l到r之间的每个数xor与x. 这题 ...
- POJ 2777 Count Color (线段树成段更新+二进制思维)
题目链接:http://poj.org/problem?id=2777 题意是有L个单位长的画板,T种颜色,O个操作.画板初始化为颜色1.操作C讲l到r单位之间的颜色变为c,操作P查询l到r单位之间的 ...
- hdu 4747【线段树-成段更新】.cpp
题意: 给出一个有n个数的数列,并定义mex(l, r)表示数列中第l个元素到第r个元素中第一个没有出现的最小非负整数. 求出这个数列中所有mex的值. 思路: 可以看出对于一个数列,mex(r, r ...
- HDU1698_Just a Hook(线段树/成段更新)
解题报告 题意: 原本区间1到n都是1,区间成段改变成一个值,求最后区间1到n的和. 思路: 线段树成段更新,区间去和. #include <iostream> #include < ...
- HDU 3577 Fast Arrangement ( 线段树 成段更新 区间最值 区间最大覆盖次数 )
线段树成段更新+区间最值. 注意某人的乘车区间是[a, b-1],因为他在b站就下车了. #include <cstdio> #include <cstring> #inclu ...
- poj 3468 A Simple Problem with Integers 【线段树-成段更新】
题目:id=3468" target="_blank">poj 3468 A Simple Problem with Integers 题意:给出n个数.两种操作 ...
- POJ3468_A Simple Problem with Integers(线段树/成段更新)
解题报告 题意: 略 思路: 线段树成段更新,区间求和. #include <iostream> #include <cstring> #include <cstdio& ...
- poj 3648 线段树成段更新
线段树成段更新需要用到延迟标记(或者说懒惰标记),简单来说就是每次更新的时候不要更新到底,用延迟标记使得更新延迟到下次需要更新or询问到的时候.延迟标记的意思是:这个区间的左右儿子都需要被更新,但是当 ...
随机推荐
- 《TCP/IP详解 卷一》读书笔记-----DNS
1.DNS是一个分布式数据库系统用来提供主机名和IP地址之间的映射,之所以称为分布式原因的原因是因特网上没有一台主机知道这类映射的全部信息,当然也不可能做到,因为数据量实在太大了 2.应用程序通过一个 ...
- 分享一个解决MySQL写入中文乱码的方法
分享一个解决MySQL写入中文乱码的方法 之前有发帖请教过如何解决MySQL写入中文乱码的问题.但没人会,或者是会的人不想回答.搜索网上的答案并尝试很多次无效,所以当时就因为这个乱码问题搁浅了一个软件 ...
- 如何实现ZBrush中部分模型的选择和隐藏
在ZBrush中制作雕刻比较庞大细节又很丰富模型的时候,有时你可能只想显示模型的某些部分,有些部分挡住了视线想要暂时隐藏.ZBrush®软件中有一个选项功能使这项操作变得相当简单,像其他功能一样,使用 ...
- 第16章 Windows线程栈
16.1 线程栈及工作原理 (1)线程栈简介 ①系统在创建线程时,会为线程预订一块地址空间(即每个线程私有的栈空间),并调拨一些物理存储器.默认情况下,预订1MB的地址空间并调拨两个页面的存储器. ② ...
- C# using 三种使用方式 C#中托管与非托管 C#托管资源和非托管资源区别
1.using指令.using + 命名空间名字,这样可以在程序中直接用命令空间中的类型,而不必指定类型的详细命名空间,类似于Java的import,这个功能也是最常用的,几乎每个cs的程序都会用到. ...
- Volley(四)—— ImageLoader & NetworkImageView
Volley(四)—— ImageLoader & NetworkImageView ImageLoader是一个加载网络图片的封装类,其内部还是由ImageRequest来实现的.但因为源码 ...
- mysqli预处理和事务处理
1 应用环境 mysqli预处理功能(大量数据处理时使用) 2 步骤 a)mysqli连接数据库 $mysqli = new mysqli('localhost','root','root','chu ...
- .Net core Linux环境安装
10月份的时候在自己电脑上搭了开发环境,当时跑完Welcome后就搁置了一段时间,最近有一个小项目要正式采用core来开发并部署在linux环境下,于是在Linux上也搭建一个运行环境. 虽然不经常使 ...
- 敏捷软件开发 Agile software Development(转)
原文链接: http://www.cnblogs.com/kkun/archive/2011/07/06/2099253.html 敏捷软件开发 Agile software Development ...
- js学习第二篇简单语法
字符串(String)字面量 可以使用单引号或双引号 数组(Array)字面量 定义一个数组: [40, 100, 1, 5, 25, 10] 对象(Object)字面量 定义一个对象: {first ...