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询问到的时候.延迟标记的意思是:这个区间的左右儿子都需要被更新,但是当 ...
随机推荐
- Unity3D实现赛车的灯光效果
车灯的需求 在赛车游戏中,遇到灯光弱的环境,赛车车可以打开前车灯照亮路边及前方,那一定是非常酷! 也见过虚拟现实项目通过Unity模拟汽车车灯的效果,但是我还没有想到好的思路来实现. 我的思路 使用( ...
- 让input框只能输入数字
var oInput = document.querySelector("input");oInput.onkeyup = function () { var value = th ...
- Nginx反向代理+负载均衡简单实现(https方式)
背景:A服务器(192.168.1.8)作为nginx代理服务器B服务器(192.168.1.150)作为后端真实服务器 现在需要访问https://testwww.huanqiu.com请求时从A服 ...
- ST3插件——PlainTasks的使用
今天看到一个有意思的ST3插件,可以进行简单的任务管理. 安装很简单:ctrl + shift + p,输入install回车,再输入plaintasks回车即可. 以下是一些支持的操作,更多的操作请 ...
- 22Spring_JdbcTemplatem模板工具类的使用——使用外部属性文件来配置(properties)
前一篇文章写得是xml文件来配置数据库连接的.但是为了方便,我们实际中采用的是properties文件的方式来配置数据库的.修改properties 文件 会比 修改 xml文件 方便. 做法是: 将 ...
- 作业调度Quartz.NET
Quartz.NET是一个开源的作业调度框架,是OpenSymphony 的 Quartz API的.NET移植,它用C#写成,可用于winform和asp.net应用中.它提供了巨大的灵活性而不牺牲 ...
- WEB 安全之 SQL注入<一> 盲注
SQL注入是一个比较"古老"的话题,虽然现在存在这种漏洞的站点比较少了,我们还是有必要了解一下它的危害,及其常用的手段,知己知彼方能百战不殆.进攻与防守相当于矛和盾的关系,我们如果 ...
- CUDA安装及配置:Windows 7 64位环境
最近又有新的项目要做了,这次是关于CUDA---多核高性能计算的问题,所以最近一直在学习CUDA的编程问题,昨天安装软件完毕,运行第一个程序的时候还是遇到很多问题.所以这里给大家一起分享一下, 有和我 ...
- 【原创】Junit4详解一:Junit总体介绍
Junit是一个可编写重复测试的简单框架,是基于Xunit架构的单元测试框架的实例.Junit4最大的改进是大量使用注解(元数据),很多实际执行过程都在Junit的后台做完了,而且写test case ...
- python 字符编码练习
通过下面的练习,加深对python字符编码的认识 # \x00 - \xff 256个字符 >>> a = range(256)>>> b = bytes(a) # ...