HDU 3397 Sequence operation

本文介绍了一种算法用于求解给定区间内的最长连续1,与POJ3667Hotel问题思路相似,涉及区间操作、状态更新和长度计算。

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

重点是求给定区间的最长连续1,这个和poj 3667hotel思路相似

#include <cstdio>
using namespace std;
int in[100010]; 
struct Node
{
    int left, right,sum;
    int stat;               // 0:区间全为0,1:区间全为1,2:区间有部分为0部分为1
    int lmax, rmax, amax;   // lmax:包含最左边元素最长1的长度,rmax:包含最右边元素最长1的长度
} tree[300010];               // amax:区间中最长1的长度

int min(int a,int b){
	return a>b?b:a;
}
int max(int a,int b){
	return a>b?a:b;
}
void updatestatus(int id)
{
    if (tree[id].stat == 2)
    {
        if (tree[id*2].stat == tree[id*2+1].stat && tree[id*2].stat != 2)
            tree[id].stat = tree[id*2].stat;
    }
}
void updatelength(int id)
{
    if (tree[id].stat == 1)
		tree[id].sum = tree[id].lmax = tree[id].rmax = tree[id].amax =tree[id].right - tree[id].left + 1;
    else if (tree[id].stat == 0)
        tree[id].sum = tree[id].lmax = tree[id].rmax = tree[id].amax = 0;
    else
    {
		tree[id].sum = tree[id*2].sum + tree[id*2+1].sum;
        tree[id].amax = max(max(tree[id*2].amax, tree[id*2+1].amax), tree[id*2].rmax + tree[id*2+1].lmax);
        tree[id].lmax = tree[id*2].lmax;
        tree[id].rmax = tree[id*2+1].rmax;
        if (tree[id*2].stat == 1)
            tree[id].lmax += tree[id*2+1].lmax;
        if (tree[id*2+1].stat == 1)
            tree[id].rmax += tree[id*2].rmax;
    }
}
void Build(int l, int r, int id)
{
    tree[id].left = l; tree[id].right = r;
    tree[id].lmax = tree[id].rmax = tree[id].amax =0;
	if (l == r){
		if(in[l]){
			tree[id].sum=1;
			tree[id].stat=1;
			tree[id].lmax = tree[id].rmax = tree[id].amax =1;
		}
		else{
			tree[id].sum=0;
			tree[id].stat=0;
			tree[id].lmax = tree[id].rmax = tree[id].amax =0;
		}
		return;
	}
    int m = (l + r) / 2;
    Build(l, m, id * 2);
    Build(m + 1, r, id * 2 + 1);
	tree[id].sum=tree[id*2].sum+tree[id*2+1].sum;
	if (tree[id*2].stat == tree[id*2+1].stat && tree[id*2].stat != 2)
		tree[id].stat = tree[id*2].stat;
	else
		tree[id].stat = 2;
	updatelength(id);            //记着更新状态和长度
}
void update(int l,int r,int flag,int id){
	if(tree[id].stat==flag)
		return;
	if(tree[id].left==l && tree[id].right==r){
		tree[id].stat=flag;
		updatelength(id);
		return;
	}
	if(tree[id].stat!=2){        // 要下传标记
		tree[id*2].stat = tree[id*2+1].stat = tree[id].stat;
        tree[id].stat = 2;
        updatelength(id*2);
        updatelength(id*2+1);
	}
	int m = (tree[id].left + tree[id].right) / 2;
	if (r <= m)
        update(l, r, flag, id * 2);
    else if (l > m)
        update(l , r, flag, id * 2 + 1);
    else
        update(l, m, flag, id * 2), update(m + 1, r, flag, id * 2 + 1);
    updatestatus(id);         //记着更新状态和长度
    updatelength(id);
}
void updatexor(int l,int r,int id){
	if(tree[id].left==l && tree[id].right==r)
		if(tree[id].stat==1 || tree[id].stat==0){
			tree[id].stat=1^tree[id].stat;
			updatelength(id);
			return;
		}
	if(tree[id].stat!=2){             // 要下传标记
		tree[id*2].stat = tree[id*2+1].stat = tree[id].stat;
        tree[id].stat = 2;
        updatelength(id*2);
        updatelength(id*2+1);
	}
	int m = (tree[id].left + tree[id].right) / 2;
	if (r <= m)
        updatexor(l, r,id * 2);
    else if (l > m)
        updatexor(l , r, id * 2 + 1);
    else
        updatexor(l, m, id * 2), updatexor(m + 1, r,id * 2 + 1);
	updatestatus(id);
    updatelength(id);              //记着更新状态和长度
}
int querysum(int l,int r,int id){
	if(tree[id].stat==0)return 0;                 
	if(tree[id].stat==1)return r-l+1;
	if(tree[id].left==l && tree[id].right==r)
		return tree[id].sum;
	int m = (tree[id].left + tree[id].right) / 2;     //这里不用把标记下传,上面情况已包括
	if (r <= m)
        return querysum(l, r,id * 2);
    else if (l > m)
        return querysum(l , r, id * 2 + 1);
    else
        return querysum(l, m, id * 2)+querysum(m + 1, r,id * 2 + 1);
}
int querycon(int l,int r,int id){
	if(tree[id].stat==0)return 0;
	if(tree[id].stat==1)return r-l+1;
	if(tree[id].left==l && tree[id].right==r)return tree[id].amax;
	int m = (tree[id].left + tree[id].right) / 2;       //这里不用把标记下传,上面情况已包括
	if (r <= m)
        return querycon(l, r,id * 2);
    else if (l > m)
        return querycon(l , r, id * 2 + 1);
    else{
        int ans1=querycon(l, m, id * 2);
		int ans2=querycon(m + 1, r,id * 2 + 1);
		int ans3=min(tree[id*2].rmax,m-l+1)+min(tree[id*2+1].lmax,r-m);
		return max(max(ans1,ans2),ans3);
	}
}
int main()
{
    int N, M,T,t,i;
    int len,a,b;
	scanf("%d",&T);
	for(t=1;t<=T;t++){
		scanf("%d %d", &N, &M);
		for(i=0;i<N;i++)
			scanf("%d",&in[i]);
		Build(0, N-1, 1);
		for (int i = 0; i < M; i++){
			int tem;
			scanf("%d %d %d", &tem,&a,&b);
			if (tem==0)
				update(a,b,0,1);
			else if(tem==1)
				update(a,b,1,1);
			else if(tem==2)
				updatexor(a,b,1);
			else if(tem==3)
				printf("%d\n",querysum(a,b,1));
			else if(tem==4)
				printf("%d\n",querycon(a,b,1));
		}
	}
    return 0;
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值