HDU3397--Sequence operation

本文探讨了一种用于处理包含'0'和'1'字符序列的操作算法,包括改变字符、输出特定区间内'1'的数量、最长连续'1'字符串长度等操作,通过构建线段树优化查询效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

 

/*
GANK,直接一个标记.如果是异或则更新到全是0或全是1的地方
*/
#include <iostream>
#include <cstring>
#include <cstdio>
#include <string>
using namespace std;
#define maxn 100008
#define lson 2*id,l,mid
#define rson 2*id+1,mid+1,r
int A[maxn];
inline int max(int a,int b,int c)
{
	if(a<b)a=b;
	if(a<c)a=c;
	return a;
}
struct ST
{
	int l,r,len,llen,rlen,set,maxlen;
}st[4*maxn];
void PushUp(int id)
{
	st[id].len=st[2*id].len+st[2*id+1].len;
	st[id].llen=(st[2*id].llen==st[2*id].r-st[2*id].l+1?st[2*id].len+st[2*id+1].llen:st[2*id].llen);
	st[id].rlen=(st[2*id+1].rlen==st[2*id+1].r-st[2*id+1].l+1?st[2*id+1].len+st[2*id].rlen:st[2*id+1].rlen);
	st[id].maxlen=max(st[2*id].maxlen,st[2*id+1].maxlen,st[2*id].rlen+st[2*id+1].llen);
}
void PushDown(int id)
{
	if(st[id].set!=-1)
	{
		st[2*id].set=st[2*id+1].set=st[id].set;
		if(st[id].set)
		{
			st[2*id].len=st[2*id].llen=st[2*id].rlen=st[2*id].maxlen=st[2*id].r-st[2*id].l+1;
			st[2*id+1].len=st[2*id+1].llen=st[2*id+1].rlen=st[2*id+1].maxlen=st[2*id+1].r-st[2*id+1].l+1;
		}
		else
		{
			st[2*id].len=st[2*id].llen=st[2*id].rlen=st[2*id].maxlen=0;
			st[2*id+1].len=st[2*id+1].llen=st[2*id+1].rlen=st[2*id+1].maxlen=0;
		}
		st[id].set=-1;
	}
}
void buildtree(int id,int l,int r)
{
	st[id].l=l;
	st[id].r=r;
	if(l==r)
	{
		st[id].len=st[id].rlen=st[id].llen=st[id].maxlen=A[l];
		st[id].set=A[l];
		return;
	}
	int mid=(l+r)>>1;
	buildtree(lson);
	buildtree(rson);
	PushUp(id);
	st[id].set=-1;
}
void update(int id,int l,int r,int ope)
{
	if(st[id].l==l && st[id].r==r)
	{
		if(ope==0)
		{
			st[id].set=0;
			st[id].len=st[id].rlen=st[id].llen=st[id].maxlen=0;
			return;
		}
		if(ope==1)
		{
			st[id].set=1;
			st[id].len=st[id].rlen=st[id].llen=st[id].maxlen=st[id].r-st[id].l+1;
			return;
		}
		if(ope==2)
		{
			if(st[id].set!=-1)
			{
				st[id].set^=1;
				st[id].len=st[id].rlen=st[id].llen=st[id].maxlen=st[id].set?st[id].r-st[id].l+1:0;
				return;
			}
		}
	}
	PushDown(id);
	if(st[2*id].r >= r)
	{
		update(2*id,l,r,ope);
		PushUp(id);
		return;
	}
	if(st[2*id+1].l <= l)
	{
		update(2*id+1,l,r,ope);
		PushUp(id);
		return;
	}
	update(2*id,l,st[2*id].r,ope);
	update(2*id+1,st[2*id+1].l,r,ope);
	PushUp(id);
}
int query(int id,int l,int r,int ope)
{
	if(st[id].l==l && st[id].r==r)
	{
		if(ope==3)
		{
			return st[id].len;
		}
		if(ope==4)
		{
			return st[id].maxlen;
		}
	}
	PushDown(id);
	if(st[2*id].r >= r)
	{
		return query(2*id,l,r,ope);
	}
	if(st[2*id+1].l <= l)
	{
		return query(2*id+1,l,r,ope);
	}
	if(ope==3)
	{
		return query(2*id,l,st[2*id].r,ope)+query(2*id+1,st[2*id+1].l,r,ope);
	}
	else
	{
		int lllen=min(st[2*id].rlen,st[2*id].r-l+1);
		int rrlen=min(st[2*id+1].llen,r-st[2*id+1].l+1);
		return max(lllen+rrlen,query(2*id,l,st[2*id].r,ope),query(2*id+1,st[2*id+1].l,r,ope));
	}
}
int main()
{
	int t;
	scanf("%d",&t);
	while(t--)
	{
		int n,m;
		scanf("%d%d",&n,&m);
		for(int i=1;i<=n;i++)
		{
			scanf("%d",&A[i]);
		}
		int ope,u,v;
		buildtree(1,1,n);
		for(int i=1;i<=m;i++)
		{
			scanf("%d%d%d",&ope,&u,&v);
			if(ope!=3 && ope!=4)
			{
				update(1,u+1,v+1,ope);
			}
			else printf("%d\n",query(1,u+1,v+1,ope));
		}
	}
	return 0;
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值