Sequence operation

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 4952    Accepted Submission(s): 1452

Problem Description
lxhgww got a sequence contains n characters which are all '0's or '1's.

We have five operations here:

Change operations:

0 a b change all characters into '0's in [a , b]

1 a b change all characters into '1's in [a , b]

2 a b change all '0's into '1's and change all '1's into '0's in [a, b]

Output operations:

3 a b output the number of '1's in [a, b]

4 a b output the length of the longest continuous '1' string in [a , b]
 
Input
T(T<=10) in the first line is the case number.

Each case has two integers in the first line: n and m (1 <= n , m <= 100000).

The next line contains n characters, '0' or '1' separated by spaces.

Then m lines are the operations:

op a b: 0 <= op <= 4 , 0 <= a <= b < n.
 
Output
For each output operation , output the result.
 
Sample Input
1
10 10
0 0 0 1 1 0 1 0 1 1
1 0 2
3 0 5
2 2 2
4 0 4
0 3 6
2 3 7
4 2 8
1 0 5
0 5 6
3 3 9
 
Sample Output
5
2
6
5
 
Author
lxhgww&&shǎ崽
 
Source
 
Recommend
lcy
 
题意:
给你一个0,1数组。你可以对数组进行以下操作。
0 x y   把[x,y]之间的元素置为0。
1 x y   把[x,y]之间的元素置为1。
2 x y   把[x,y]之间的元素置为1变成0,0变成1。
3 x y   求[x,y]之间元素1的个数。
4 x y   求[x,y]之间最长连续1的长度。
思路:
对于0,1,3,4操作都很传统。区间更新区间统计。但是由于多了2操作所以就要多维护关于0的信息。这样进行2操作的时候之间交换1和0的信息就行了。还有查询的时候也有注意的地方。开始没注意那个地方导致wa数次。反复检查冗长的代码无数次。。。。可怜我的时间呀。。。哎。。。。。
详细见代码:
#include<algorithm>
#include<iostream>
#include<string.h>
#include<sstream>
#include<stdio.h>
#include<math.h>
#include<vector>
#include<string>
#include<queue>
#include<set>
#include<map>
using namespace std;
const int INF=0x3f3f3f3f;
const int maxn=100100;
int sta[maxn<<2],ml0[maxn<<2],mr0[maxn<<2],ml1[maxn<<2];//sta为标记。ml1为1左端连续。ml0为0左端连续
int mr1[maxn<<2],ma1[maxn<<2],ma0[maxn<<2],one[maxn<<2];//ma1为最大1连续数.one记录1的个数
void opp(int L,int R,int k)//对于2操作。0和1互换
{
swap(ma0[k],ma1[k]);
swap(ml0[k],ml1[k]);
swap(mr0[k],mr1[k]);
one[k]=R-L-one[k]+1;
}
void pushup(int L,int R,int k)//下传标记
{
int ls,rs,mid;
ls=k<<1;
rs=ls|1;
mid=(L+R)>>1;
ml0[k]=ml0[ls];
mr0[k]=mr0[rs];
ml1[k]=ml1[ls];
mr1[k]=mr1[rs];
if(ml0[ls]==mid-L+1)
ml0[k]+=ml0[rs];
if(mr0[rs]==R-mid)
mr0[k]+=mr0[ls];
if(ml1[ls]==mid-L+1)
ml1[k]+=ml1[rs];
if(mr1[rs]==R-mid)
mr1[k]+=mr1[ls];
ma1[k]=max(ma1[ls],ma1[rs]);
ma1[k]=max(ma1[k],mr1[ls]+ml1[rs]);
ma0[k]=max(ma0[ls],ma0[rs]);
ma0[k]=max(ma0[k],mr0[ls]+ml0[rs]);
one[k]=one[ls]+one[rs];
}
void pushdown(int L,int R,int k)//上传
{
int ls,rs,mid;
ls=k<<1;
rs=ls|1;
mid=(L+R)>>1;
//printf("mark %d->%d and %d->%d %d\n",L,mid,mid+1,R,sta[k]);
if(sta[k]==0)
{
sta[ls]=sta[rs]=0;
ma0[ls]=ml0[ls]=mr0[ls]=mid-L+1;
ma1[ls]=ml1[ls]=mr1[ls]=one[ls]=ma1[rs]=ml1[rs]=mr1[rs]=one[rs]=0;
ma0[rs]=ml0[rs]=mr0[rs]=R-mid; }
else if(sta[k]==1)
{
sta[ls]=sta[rs]=1;
ma0[ls]=ml0[ls]=mr0[ls]=ma0[rs]=ml0[rs]=mr0[rs]=0;
ma1[ls]=ml1[ls]=mr1[ls]=one[ls]=mid-L+1;
ma1[rs]=ml1[rs]=mr1[rs]=one[rs]=R-mid;
}
else
{
if(sta[ls]!=-1)//2操作对于0,1标记直接0,1标记互换
{
if(sta[ls]==2)//原先有2直接变-1
sta[ls]=-1;
else
sta[ls]^=1;
}
else
sta[ls]=2;
if(sta[rs]!=-1)
{
if(sta[rs]==2)
sta[rs]=-1;
else
sta[rs]^=1;
}
else
sta[rs]=2;
opp(L,mid,ls);
opp(mid+1,R,rs);
}
sta[k]=-1;
}
void btree(int L,int R,int k)
{
int ls,rs,mid;
sta[k]=-1;
if(L==R)
{
scanf("%d",&one[k]);
if(one[k])
{
ma1[k]=ml1[k]=mr1[k]=1;
ma0[k]=ml0[k]=mr0[k]=0;
}
else
{
ma1[k]=ml1[k]=mr1[k]=0;
ma0[k]=ml0[k]=mr0[k]=1;
}
return ;
}
ls=k<<1;
rs=ls|1;
mid=(L+R)>>1;
btree(L,mid,ls);
btree(mid+1,R,rs);
pushup(L,R,k);
//printf("%d->%d\n",L,R);
//printf("%d---%d----%d\n",ml1[k],mr1[k],one[k]);
}
void update(int L,int R,int l,int r,int k,int op)
{
int ls,rs,mid;
if(l==L&&r==R)
{
if(op==0)
{
sta[k]=0;
ma0[k]=ml0[k]=mr0[k]=R-L+1;
ma1[k]=ml1[k]=mr1[k]=one[k]=0;
}
else if(op==1)
{
sta[k]=1;
ma0[k]=ml0[k]=mr0[k]=0;
ma1[k]=ml1[k]=mr1[k]=one[k]=R-L+1;
}
else
{
if(sta[k]==-1)
sta[k]=2;
else if(sta[k]==2)
sta[k]=-1;
else
sta[k]^=1;
opp(L,R,k);
}
//printf("mark %d->%d %d\n",L,R,op);
//printf("%d->%d\n",L,R);
//printf("%d---%d----%d\n",ml1[k],mr1[k],one[k]);
return ;
}
if(sta[k]!=-1)
pushdown(L,R,k);
ls=k<<1;
rs=ls|1;
mid=(L+R)>>1;
if(l>mid)
update(mid+1,R,l,r,rs,op);
else if(r<=mid)
update(L,mid,l,r,ls,op);
else
{
update(L,mid,l,mid,ls,op);
update(mid+1,R,mid+1,r,rs,op);
}
pushup(L,R,k);
//printf("%d->%d\n",L,R);
//printf("%d---%d----%d\n",ml1[k],mr1[k],one[k]);
}
int qu(int L,int R,int l,int r,int k,int op)
{
int ls,rs,mid,tmp,ll,rr;
if(sta[k]==0)
return 0;
if(sta[k]==1)
return r-l+1;
if(l==L&&r==R)
{
if(op==3)
return one[k];
else
return ma1[k];
}
if(sta[k]!=-1)
pushdown(L,R,k);
ls=k<<1;
rs=ls|1;
mid=(L+R)>>1;
if(l>mid)
return qu(mid+1,R,l,r,rs,op);
else if(r<=mid)
return qu(L,mid,l,r,ls,op);
else
{
if(op==3)
return qu(L,mid,l,mid,ls,op)+qu(mid+1,R,mid+1,r,rs,op);
else//4对于分离操作尤其注意!!最大值只能是以下几种情况。
{
tmp=max(qu(L,mid,l,mid,ls,op),qu(mid+1,R,mid+1,r,rs,op));//最大值在左儿子或右儿子中
ll=max(mid-mr1[ls]+1,l);//最大值在中间区域
rr=min(mid+ml1[rs],r);//注意范围
tmp=max(tmp,rr-ll+1);
return tmp;
}
} }
int main()
{
int t,n,m,op,a,b; scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
btree(1,n,1);
while(m--)
{
scanf("%d%d%d",&op,&a,&b);
a++,b++;
if(op<3)
update(1,n,a,b,1,op);
else
printf("%d\n",qu(1,n,a,b,1,op));
}
}
return 0;
}

hdu 3397 Sequence operation(很有意思的线段树题)的更多相关文章

  1. HDU 3397 Sequence operation(线段树)

    HDU 3397 Sequence operation 题目链接 题意:给定一个01序列,有5种操作 0 a b [a.b]区间置为0 1 a b [a,b]区间置为1 2 a b [a,b]区间0变 ...

  2. hdu 3397 Sequence operation(线段树:区间更新)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3397 题意:给你一个长度为n的0,1序列,支持下列五种操作, 操作0(0 a b):将a到b这个区间的 ...

  3. hdu 3397 Sequence operation (线段树 区间合并 多重标记)

    链接:http://acm.hdu.edu.cn/showproblem.php?pid=3397 题意: 给你一串01串,有5种操作 0. 区间全部变为0 1.区间全部变为1 2.区间异或 3.询问 ...

  4. 【线段树】HDU 3397 Sequence operation 区间合并

    操作 Change operations: 0 a b change all characters into '0's in [a , b] 1 a b change all characters i ...

  5. HDU 5919 Sequence II(可持久化线段树)

    [题目链接]http://acm.hdu.edu.cn/showproblem.php?pid=5919 [题目大意] 给出一个数列,每次查询数列中,区间非重元素的下标的中位数.查询操作强制在线. [ ...

  6. (简单) HDU 3397 Sequence operation,线段树+区间合并。

    Problem Description lxhgww got a sequence contains n characters which are all '0's or '1's. We have ...

  7. hdu 3397 Sequence operation 线段树 区间更新 区间合并

    题意: 5种操作,所有数字都为0或1 0 a b:将[a,b]置0 1 a b:将[a,b]置1 2 a b:[a,b]中的0和1互换 3 a b:查询[a,b]中的1的数量 4 a b:查询[a,b ...

  8. hdu 3397 Sequence operation 线段树

    题目链接 给出n个数, 每个数是0或1, 给5种操作, 区间变为1, 区间变为0, 区间0,1翻转, 询问区间内1的个数, 询问区间内最长连续1的个数. 需要将数组开成二维的, 然后区间0, 1翻转只 ...

  9. HDU 3397 Sequence operation 多标记线段树

    /* 一开始维护了两个标记 开了两个数组 想的是 可能当前两种操作都要做 但是太复杂了 不好处理 其实 当前要做的标记可以只有一个 我们在Insert的时候 要打的标记是2即翻转区间: 1.如果原来是 ...

随机推荐

  1. 13行代碼開發出来的PHP框架[转]

    <?PHP /** PHP極簡框架 交流: QQ群: 223494678 http://7di.net 用法 http://URL http://URL/hello http://URL/sev ...

  2. Github托管代码步骤

    总结一下Github上项目托管步骤: Step 1:注册Github帐号,并创建一个repository,假如仓库名为test: Step 2:安装本地Git: sudo apt-get instal ...

  3. 大数据时代的技术hive:hive介绍

    我最近研究了hive的相关技术,有点心得,这里和大家分享下. 首先我们要知道hive到底是做什么的.下面这几段文字很好的描述了hive的特性: 1.hive是基于Hadoop的一个数据仓库工具,可以将 ...

  4. 【转】IOS开发:[1]Xcode5界面入门

    ios开发离不开xcode,这篇以xcode5界面来介绍一下xcode的界面都有哪些内容. 工具/原料 xcode5 整体来看区域有哪些? 1 首先我们先整体来看一下,xcode5界面可以分为五大主要 ...

  5. 从IT方法论来谈RUP

    在<从IT方法论来谈Scrum>中我谈到了6Ways方法框架,本篇仍用6Ways方法框架来概括的谈谈RUP方法. 软件开发过程描述了软件构造.部署和维护的一种方法.统一过程(Unified ...

  6. C# 中对WinForm窗体中的控件快速设置TableIndex次序

    点击“视图”--“Tab键顺序”,然后便可设置.

  7. crontab的安装及crontab命令介绍

    前一天学习了 at 命令是针对仅运行一次的任务,循环运行的例行性计划任务,linux系统则是由 cron (crond) 这个系统服务来控制的.Linux 系统上面原本就有非常多的计划性工作,因此这个 ...

  8. [搜片神器]之DHT网络爬虫的代码实现方法

    继续接着第一篇写:使用C#实现DHT磁力搜索的BT种子后端管理程序+数据库设计(开源)[搜片神器] 谢谢园子朋友的支持,已经找到个VPS进行测试,国外的服务器: http://www.sosobta. ...

  9. struts2类型转换与校验总结

    1.struts2的类型转换分为全部变量转变和局部变量转变. 2.struts2对8中常见的基本类型的属性变量,可以自动转换.如果是User对象,可以手动简历UserAction-coversion. ...

  10. 判断是否为BST

    递归的方法,用返回false的方法.中序遍历的想法很好,空间浪费.遍历的过程记录上一次的值进行比较. //题目描述 // //请实现一个函数,检查一棵二叉树是否为二叉查找树. //给定树的根结点指针T ...