链接;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. 在属性property做一些简单的验证

    开发C#的程序,写到属性property时,我们可以在Set方法中做一些简单的规则验证: 如下面,Insus.NET写一个Age属性,只允许用户输入10以内的数字: class AA { privat ...

  2. .NET Core 3.0 跟踪

    Preview1: https://blogs.msdn.microsoft.com/dotnet/2018/12/04/announcing-net-core-3-preview-1-and-ope ...

  3. 算法相关——Java排序算法之冒泡排序(二)

    0. 前言 本系列文章将介绍一些常用的排序算法.排序是一个非常常见的应用场景,也是开发岗位面试必问的一道面试题,有人说,如果一个企业招聘开发人员的题目中没有排序算法题,那说明这个企业不是一个" ...

  4. Luogu P4016 负载平衡问题

    传说中的网络流24题之一,我刷的第二题菜. 据说这种东西做完了就可以有质的飞越?不过看着这些Luogu评级就有点蒙蔽. 首先我们看一下题目发现这不是均分纸牌的加强板吗,但是那个环的操作极大地限制了我的 ...

  5. System.Data.SqlClient.SqlException:“对象名 'customer' 无效。"

    连接数据库出错, 错误原因:表名错误.

  6. 自从硬派网倒闭后,就没有什么好看的IT硬件网站了

    RT

  7. python2.6升级到3.3.0 以及依赖库在迁移时的处理

    线上服务器python版本默认是2.6,由于业务程序要求,需要将python升级到3.3.0, 操作记录如下: Cenots6.8默认安装的是2.6版本,要更新升级需安装下gcc: [root@ope ...

  8. JDK+JAVA+maven+IDEA

    JDK+JAVA https://jingyan.baidu.com/article/6dad5075d1dc40a123e36ea3.html maven+IDEA http://blog.csdn ...

  9. poj1426 Find The Multiple(c语言巧解)

    Find The Multiple Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 36335   Accepted: 151 ...

  10. Word frequency program ver.1

    先吐槽一下自己 做这个作业的时候完全没有提前考虑好时间 导致要提交前一天晚上通宵写代码 而且还满满的bug TAT 缓一口气 程序还在继续写 先把有点累 想着先把博客写了 PART I 预计时间: 语 ...