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询问到的时候.延迟标记的意思是:这个区间的左右儿子都需要被更新,但是当 ...
随机推荐
- A*算法详解 BZOJ 1085骑士精神
转载1:A*算法入门 http://www.cppblog.com/mythit/archive/2009/04/19/80492.aspx 在看下面这篇文章之前,先介绍几个理论知识,有助于理解A*算 ...
- Hibernate之Query接口的uniqueResult()方法
如果查询返回多个值用list()方法 public void testQuery(){ Configuration config = new Configuration().configure(); ...
- 【转载】Jmeter获取响应结果中参数出现的次数
在测试中,有时候会遇到要统计响应结果中某个参数出现了多少次,如果量级很大,一个一个数不太现实,下面讲一下实现自动打印出该参数出现的次数的方法. 例如我的响应信息为:{"ip":&q ...
- JMeter学习(十九)JMeter测试MongoDB
JMeter测试MongoDB性能有两种方式,一种是利用JMeter直接进行测试MongoDB,还有一种是写Java代码方式测试MongoDB性能. 第一种方法 1.编写Java代码,内容如下: pa ...
- Block 的基本用法
iOS中Block的基础用法 转载自简书 本文简介 本章不会对Block做过多的实现研究.只是讲解基本的用法.纯粹基础知识.结合实际项目怎么去做举例.Block使用场景,可以在两个界面的传值,也可以对 ...
- 关于MySql全文索引
从 Mysql 4.0 开始就支持全文索引功能,但是 Mysql 默认的最小索引长度是 4.如果是英文默认值是比较合理的,但是中文绝大部分词都是2个字符,这就导致小于4个字的词都不能被索引,全文索引功 ...
- Microsoft Visual Studio 下载转帖
1.VS2010 2.VS2012 Visual Studio 2012 Ultimate旗舰版序列号: YKCW6-BPFPF-BT8C9-7DCTH-QXGWC YQ7PR-QTHDM-HCBCV ...
- 通过jekyll建立静态网页
部署一个网站需要三个步骤:(1) generating the site, (2) deploying it to the public Internet, and (3) assigning it ...
- Linux Linux程序练习十(网络编程大文件发送)
//网络编程客户端--大文件传输 #include <stdio.h> #include <stdlib.h> #include <string.h> #inclu ...
- ASP.NET中进行消息处理(MSMQ) 三
在本文的前两篇文章里对MSMQ的相关知识点进行了介绍,很多阅读过这前两篇文章的朋友都曾问到过这样一些问题: 1.如何把MSMQ应用到实际的项目中去呢? 2.可不可以介绍一个实际的应用实例? 3. ...