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询问到的时候.延迟标记的意思是:这个区间的左右儿子都需要被更新,但是当 ...
随机推荐
- Ubuntu 14.04 LTS Server 无法挂载光盘 启动initramfs等问题
今天需要在戴尔R410服务器上装64位的Linux,师兄给了个14.04的server 64位镜像.一开始打算用U盘安装,用软碟通烧写镜像之后,在服务器端设置从U盘启动,但是安装到一半出现了光盘无法挂 ...
- 如何在ZBrush中将球体演变为头发
对于头发的制作,ZBrush®是多样的,前面的教程中也有讲解,可以用球体作为子工具,用不同笔刷进行雕刻:还可以使用Z球转网格的方式.今天小编讲述一种最简单的方法,使用球体演变头发,这样的创作手法更高效 ...
- SQL Server 2005 安装图解教程(Windows)
因工作需要,好久未安装SQL Server2005,今天安装了一下,特此写下安装步骤留下笔记. 安装前准备: 先安装IIS,再安装SQL Server2005 一.安装 点击安装,如下图: 选择操作系 ...
- App_api设计
2014年,移动APP的热度丝毫没有减退,并没有像桌面软件被WEB网站那样所取代,不但如此,越来越多的传统应用.网站也都开始制作自己的移动APP,也就是我们常说的IOS客户端.android客户端.这 ...
- 06Spring_使用注解配置bean对象
Spring注解开发需要jar包 和 xml开发 一样的 ! 第一步: 新建项目, 导入jar包(就是前一篇文章里面的那几个核心jar包) 第二步: 在需要spring创建对象类上面 添加@Compo ...
- jqXHR 对象(post完成后再调用函数)
场景: function A() { B(); C(); } function B() { $.post(url, {}, function () { alert("我错了!"); ...
- C++ STL之vector详解
转自http://blog.sina.com.cn/s/blog_9f1c0931010180cy.html Vectors vector是C++标准模板库中的部分内容,它是一个多功能的,能够操作 ...
- 如何解决机器重启后MySql服务跑不起来了1067,附解决过程
今个一位同事的mysql跑不起来了,之前还好好的,问我怎么恢复,我没在她出问题的机器上弄,在自己机器上试的,最终在CTO的指导下解决了,现记录于此. 1,首先把她的mysql安装文件夹.数据结构文件. ...
- 机器学习算法 Python & R速查表
- MVC中利用自定义的ModelBinder过滤关键字
上一篇主要讲解了如何利用ActionFilter过滤关键字,这篇主要讲解如何利用自己打造的ModelBinder来过滤关键字. 首先,我们还是利用上一篇中的实体类,但是我们需要加上DataType特性 ...