链接;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. git 用法---成功添加一个文件到github

    一.git 提交 全部文件 git add . git add xx命令可以将xx文件添加到暂存区,如果有很多改动可以通过 git add -A .来一次添加所有改变的文件.注意 -A 选项后面还有一 ...

  2. .NetCore实践篇:成功解决分布式监控ZipKin聚合依赖问题(三)

    前言 读本篇文章之前,可以先读前两篇文章.为了照顾没看过的朋友,我也会稍作复习. 思考大纲: .Net架构篇:思考如何设计一款实用的分布式监控系统? 实践篇一:.NetCore实践篇:分布式监控客户端 ...

  3. C/C++中连接函数strcat的应用(简单讲解)

    有位学弟问到我如何将两个字符连接起来,想想java/python里面可以直接用+连接起来,可是C/C++里面有没有这么方便的做法呢? 答案是有的,在C语言的string.h库中有个神奇的函数叫做str ...

  4. Ubuntu apt-get提示被锁住

    执行 apt-get 时提示资源被锁住 E: Could not get lock /var/lib/dpkg/lock - open (11: Resource temporarily unavai ...

  5. js怎么将 base64转换成图片

    //获取数组最后一个元素 let hasFiles = files[Object.keys(files).pop()] // 参考上面的图片 let file = hasFiles.url let n ...

  6. 《蹭课神器》Alpha版使用说明

    <蹭课神器>是一款方便大学生蹭课的软件,目前实现了查询课表的功能,还没有实现搜索和提醒的功能.有待进一步的开发! 登录之后点击查询操作,查询课表. 课表显示如下

  7. [Intellij IDEA]_eclipse项目导入

    http://www.cnblogs.com/lindp/p/4484390.html

  8. Spring配置常识

    (1)数据源配置 <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" ...

  9. HttpServletResponse类学习

    /*//2) 乱码的解决. //设置服务器输出的编码为UTF-8---在BaseServlet处已经已经进行了设置 response.setCharacterEncoding("UTF-8& ...

  10. CI框架2.x的验证码中所遇问题解决

    用php版本是5.6,CI框架版本是2.x,在使用验证码(captcha)时,遇到一些问题. 首先,我查看框架手册,说必需的两个参数是"img_url",“img_path”,其他 ...