链接;http://acm.hdu.edu.cn/showproblem.php?pid=3397

题意:

给你一串01串,有5种操作

0. 区间全部变为0

1.区间全部变为1

2.区间异或

3.询问区间1的个数

4.询问区间被最长连续1的长度

思路:

这5个操作都是比较基础的线段树操作,难点在于有两种修改操作,这类题之前也写过,之前是乘法和加法,这个是区间亦或和区间更新值,但是思路是可以借鉴的,我们要推出这两个操作的关系,这样才能维护好这两个标记,我们用两个标记:same , rev ,分别表示区间更新值和区间异或,那么向下更新的时候如果如果有same标记,清空当前区间的rev标记,简单维护下就好了,如果有rev标记,且有same标记,那么直接对same异或维护,如果没有same标记那么就维护下区间异或就好了。

写的超爽,一遍就a了,美滋滋,还以为又要找好久的错。。

实现代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define mid int m = (l + r) >> 1
#define ll long long const int M = 1e5 + ;
int lsum1[M<<],rsum1[M<<],sum1[M<<];
int lsum0[M<<],rsum0[M<<],sum0[M<<];
int sum[M<<],same[M<<],rev[M<<];
int a[M]; void pushup(int l,int r,int rt){
mid;
sum[rt] = sum[rt<<] + sum[rt<<|];
lsum0[rt] = lsum0[rt<<]; lsum1[rt] = lsum1[rt<<];
rsum0[rt] = rsum0[rt<<|]; rsum1[rt] = rsum1[rt<<|];
if(lsum0[rt] == m-l+) lsum0[rt] += lsum0[rt<<|];
if(rsum0[rt] == r-m) rsum0[rt] += rsum0[rt<<];
if(lsum1[rt] == m-l+) lsum1[rt] += lsum1[rt<<|];
if(rsum1[rt] == r-m) rsum1[rt] += rsum1[rt<<];
sum0[rt] = max(max(sum0[rt<<],sum0[rt<<|]),lsum0[rt<<|]+rsum0[rt<<]);
sum1[rt] = max(max(sum1[rt<<],sum1[rt<<|]),lsum1[rt<<|]+rsum1[rt<<]);
} void swa(int len,int rt){
sum[rt] = len - sum[rt];
swap(lsum1[rt],lsum0[rt]);
swap(rsum1[rt],rsum0[rt]);
swap(sum1[rt],sum0[rt]);
} void pushdown(int l,int r,int rt){
mid;
if(same[rt]!=-){
rev[rt<<] = rev[rt<<|] = ;
same[rt<<] = same[rt<<|] = same[rt];
if(same[rt]){
sum[rt<<] = lsum1[rt<<] = rsum1[rt<<] = sum1[rt<<] = m-l+;
sum[rt<<|] = lsum1[rt<<|] = rsum1[rt<<|] = sum1[rt<<|] = r-m;
lsum0[rt<<] = rsum0[rt<<] = sum0[rt<<] = sum0[rt<<|] = rsum0[rt<<|] = lsum0[rt<<|] = ;
}
else{
sum[rt<<] = lsum1[rt<<] = rsum1[rt<<] = sum1[rt<<] = ;
sum[rt<<|] = lsum1[rt<<|] = rsum1[rt<<|] = sum1[rt<<|] = ;
lsum0[rt<<] = rsum0[rt<<] = sum0[rt<<] = m-l+;
sum0[rt<<|] = rsum0[rt<<|] = lsum0[rt<<|] = r-m;
}
same[rt] = -;
}
if(rev[rt]){
if(same[rt<<] != -){
same[rt<<] ^= ;
if(same[rt<<]){
sum[rt<<] = lsum1[rt<<] = rsum1[rt<<] = sum1[rt<<] = m-l+;
lsum0[rt<<] = rsum0[rt<<] = sum0[rt<<] = ;
}
else{
sum[rt<<] = lsum1[rt<<] = rsum1[rt<<] = sum1[rt<<] = ;
lsum0[rt<<] = rsum0[rt<<] = sum0[rt<<] = m-l+;
}
}
else{
rev[rt<<] ^= ;
swa(m-l+,rt<<);
}
if(same[rt<<|] != -){
same[rt<<|] ^= ;
if(same[rt<<|]){
sum[rt<<|] = lsum1[rt<<|] = rsum1[rt<<|] = sum1[rt<<|] = r-m;
sum0[rt<<|] = rsum0[rt<<|] = lsum0[rt<<|] = ;
}
else{
sum[rt<<|] = lsum1[rt<<|] = rsum1[rt<<|] = sum1[rt<<|] = ;
sum0[rt<<|] = rsum0[rt<<|] = lsum0[rt<<|] = r-m;
}
}
else{
rev[rt<<|] ^= ;
swa(r-m,rt<<|);
}
rev[rt] = ;
}
} void build(int l,int r,int rt){
same[rt] = -; rev[rt] = ;
lsum1[rt] = rsum1[rt] = lsum0[rt] = rsum0[rt] = sum0[rt] = sum1[rt] = sum[rt] = ;
if(l == r){
if(a[l]){
lsum1[rt] = sum[rt] = sum1[rt] = rsum1[rt] = ;
lsum0[rt] = rsum0[rt] = sum0[rt] = ;
}
else {
sum1[rt] = sum[rt] = sum1[rt] = rsum1[rt] = ;
lsum0[rt] = rsum0[rt] = sum0[rt] = ;
}
return ;
}
mid ;
build(lson); build(rson);
pushup(l,r,rt);
} void update_same(int L,int R,int c,int l,int r,int rt){
if(L <= l&&R >= r){
rev[rt] = ;
same[rt] = c;
if(same[rt]){
sum[rt] = lsum1[rt] = rsum1[rt] = sum1[rt] = r-l+;
lsum0[rt] = rsum0[rt] = sum0[rt] = ;
}
else{
sum[rt] = lsum1[rt] = rsum1[rt] = sum1[rt] = ;
lsum0[rt] = rsum0[rt] = sum0[rt] = r-l+;
}
return ;
}
pushdown(l,r,rt);
mid;
if(L <= m) update_same(L,R,c,lson);
if(R > m) update_same(L,R,c,rson);
pushup(l,r,rt);
} void update_rev(int L,int R,int l,int r,int rt){
if(L <= l&&R >= r){
if(same[rt] != -){
same[rt] ^= ;
if(same[rt]){
sum[rt] = lsum1[rt] = rsum1[rt] = sum1[rt] = r-l+;
lsum0[rt] = rsum0[rt] = sum0[rt] = ;
}
else{
sum[rt] = lsum1[rt] = rsum1[rt] = sum1[rt] = ;
lsum0[rt] = rsum0[rt] = sum0[rt] = r-l+;
}
}
else{
rev[rt] ^= ;
swa(r-l+,rt);
}
return ;
}
mid ;
pushdown(l,r,rt);
if(L <= m) update_rev(L,R,lson);
if(R > m) update_rev(L,R,rson);
pushup(l,r,rt);
} int query_sum(int L,int R,int l,int r,int rt){
if(L <= l&&R >= r){
return sum[rt];
}
pushdown(l,r,rt);
mid;
int ret = ;
if(L <= m) ret += query_sum(L,R,lson);
if(R > m) ret += query_sum(L,R,rson);
return ret;
} int query_max(int L,int R,int l,int r,int rt){
if(L <= l&&R >= r){
return sum1[rt];
}
pushdown(l,r,rt);
mid;
int ret = ;
if(L > m) return query_max(L,R,rson);
if(R <= m) return query_max(L,R,lson);
int t1 = query_max(L,R,lson);
int t2 = query_max(L,R,rson);
int ls = min(rsum1[rt<<],m-L+);
int rs = min(lsum1[rt<<|],R-m);
return max(max(t1,t2),ls+rs);
} int main()
{
int n,q,x,y,op,t;
scanf("%d",&t);
while(t--){
scanf("%d%d",&n,&q);
for(int i = ;i <= n;i ++)
scanf("%d",&a[i]);
build(,n,);
while(q--){
scanf("%d%d%d",&op,&x,&y);
x++; y++;
if(op == ){
update_same(x,y,,,n,);
}
else if(op == ){
update_same(x,y,,,n,);
}
else if(op == ){
update_rev(x,y,,n,);
}
else if(op == ){
printf("%d\n",query_sum(x,y,,n,));
}
else {
printf("%d\n",query_max(x,y,,n,));
}
}
}
return ;
}

hdu 3397 Sequence operation (线段树 区间合并 多重标记)的更多相关文章

  1. 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 ...

  2. hdu 3397 Sequence operation 线段树

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

  3. HDU 6638 - Snowy Smile 线段树区间合并+暴力枚举

    HDU 6638 - Snowy Smile 题意 给你\(n\)个点的坐标\((x,\ y)\)和对应的权值\(w\),让你找到一个矩形,使这个矩阵里面点的权值总和最大. 思路 先离散化纵坐标\(y ...

  4. HDU 5316——Magician——————【线段树区间合并区间最值】

    Magician Time Limit: 18000/9000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total S ...

  5. HDU 1540 Tunnel Warfare 线段树区间合并

    Tunnel Warfare 题意:D代表破坏村庄,R代表修复最后被破坏的那个村庄,Q代表询问包括x在内的最大连续区间是多少 思路:一个节点的最大连续区间由(左儿子的最大的连续区间,右儿子的最大连续区 ...

  6. Sequence operation(线段树区间多种操作)

    Sequence operation Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Othe ...

  7. (简单) HDU 3308 LCIS,线段树+区间合并。

    Problem Description Given n integers. You have two operations: U A B: replace the Ath number by B. ( ...

  8. hdu 4453 约会安排(线段树区间合并)

    约会安排 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)Total Submis ...

  9. hdu 3308 LCIS(线段树区间合并)

    题目链接:http://acm.hdu.edu.cn/showproblem.php? pid=3308 LCIS Time Limit: 6000/2000 MS (Java/Others)     ...

随机推荐

  1. Java多线程编程模式实战指南一:Active Object模式(上)

    Active Object模式简介 Active Object模式是一种异步编程模式.它通过对方法的调用与方法的执行进行解耦来提高并发性.若以任务的概念来说,Active Object模式的核心则是它 ...

  2. 利用shell脚本或者php移动某个文件夹下的文件到各自的日期组成的目录下

    背景是这样的:网站一开始访问量比较小,大家就把所有的图片文件上传到一个目录下(比如是/data/images/).后来访问量大了,图片也多了,这样就影响读取效率.所以有个这样的需求,把这些个图片文件移 ...

  3. linux中yum与rpm区别

    一.源代码形式 1.      绝大多数开源软件都是直接以原码形式发布的 2.      源代码一般会被打成.tar.gz的归档压缩文件 3.      源代码需要编译成为二进制形式之后才能够运行使用 ...

  4. 3.3《想成为黑客,不知道这些命令行可不行》(Learn Enough Command Line to Be Dangerous)——less即more

    Unix提供了两个工具查看不止文件的头部和尾部.这个功能程序叫做more,但有种更强大的变异体叫做less(起初我认为这是玩笑).less这个程序是交互性地,所以很难在输出时捕获,但是仍然为大家提供了 ...

  5. Windows 窗体中的事件顺序

    来自:https://docs.microsoft.com/zh-cn/dotnet/framework/winforms/order-of-events-in-windows-forms 对于依次处 ...

  6. Supervisor (进程管理利器) 使用说明 - 运维笔记

    一.Supervisor简单介绍supervisor是一个 Client/Server模式的系统,允许用户在类unix操作系统上监视和控制多个进程,或者可以说是多个程序.supervisor与laun ...

  7. HAOI2016 找相同字符 后缀自动机

    两个串,考虑一建一跑.枚举模式串的位置\(i\),考虑每次统计以\(i\)结尾的所有符合要求的串.在后缀自动机上走时记录当前匹配长度\(curlen\),则当前节点的贡献是\((curlen-len[ ...

  8. Visual Studio 2013编辑器+SourceTree代码管理工具及扩展工具

    Visual Studio 2013: 美国微软公司的编辑开发工具 扩展工具: Resharper:进行深度代码分析,函数深度查询(ctrl+鼠标左): Grunt:是基于Node.js的项目以自动化 ...

  9. zifutongji

    第三次作业要求我们自己写程序,我算我们班写的比较晚的了,我听他们写的都是在文件中写一段代码,然后读出来.我们班大部分都是,所以,我就想可不可以跟他们不一样呢,写一个属于自己的思路. 所以我想到了数组. ...

  10. Individual Project - Word frequency program——12061154Joy

    Description&Requirement: http://www.cnblogs.com/jiel/p/3978727.html 项目时间估计 理解项目要求: 1h 构建项目逻辑: 1h ...