HDU - 3397 Sequence operation (线段树,区间修改,亦或,查询,以及最长连续的1)

有5个操作,

0  区间全部置为0

1 区间全部置为1

2 区间的值取反,1 变0 ,0变1,

3 求区间1 的个数。

4 求区间连续最长的1.

 

思路:

lazy标记, 有 -1,0,1,2, 四种标记,

-1 是什么都没有,

0,1 算是一种操作,区间修改,

2 是一种操作,亦或。

 

因为亦或这个操作。我们存一下1 的所有数据,0的所有数据,便于以后交换。

我们要考虑一下优先级的问题,

1,无论当前节点之前是什么标记,现在给它 0,或者1 的标记,那就直接覆盖就好。

2,当前节点之前是0 或 1 标记,现在给他 2 标记,那么我们就把之前的标记亦或一下,

3,当前节点之前是 2 或者 -1,我们这个时候就要交换0 的数据和1 的数据,

然后lazy标记,之前为-1现在为2,之前为2现在为-1,因为两次亦或相当于不变。

 

#include <bits/stdc++.h>
#define mem(x,v) memset(x,v,sizeof(x)) 
#define rep(i,a,b)  for (int i = a; i < b; i++)
#define per(i,a,b)  for (int i = a; i > b; i--)
using namespace std;
typedef long long LL;
const double EPS = 1e-10;
const int INF = 0x3f3f3f3f;
const int N = 1e5+100;
struct segtree{
	int l,r,a,b;
	int w,ll1,rr1,ll,ll0,rr0,rr; // w 是区间和,ll1,ll0 从左1 或 0 的个数,rr1,rr0 从右的个数,ll,rr,区间最长1 或者 0 的个数。
	int lazy; // lazy标记,0,1,2,-1,四种标记。
	int calc_mid(){
		return (a + b)/2;
	}
	int calc_len(){
		return (b - a);
	}
	void calc_swap(){ //交换。
		swap(ll1,ll0);
		swap(rr1,rr0);
		swap(ll,rr);
		return;
	}
}f[N*2];
int n,c[N],t,m;

void push_up(int p){
	f[p].w = f[f[p].l].w + f[f[p].r].w;
	f[p].ll1 = f[f[p].l].ll1; if (f[f[p].l].ll1 == f[f[p].l].calc_len()) f[p].ll1 += f[f[p].r].ll1;
	f[p].rr1 = f[f[p].r].rr1; if (f[f[p].r].rr1 == f[f[p].r].calc_len()) f[p].rr1 += f[f[p].l].rr1;
	f[p].ll = max(f[f[p].l].ll,max(f[f[p].r].ll,f[f[p].l].rr1+f[f[p].r].ll1));

	f[p].ll0 = f[f[p].l].ll0; if (f[f[p].l].ll0 == f[f[p].l].calc_len()) f[p].ll0 +=
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值