HDU1540 Tunnel Warfare (线段树区间合并)

本文介绍了一道关于地道战模拟的经典线段树区间合并问题。通过建立线段树来模拟村庄之间的连接状态,利用线段树进行区间更新与查询,解决了村庄连续区间的动态变化问题。

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

Tunnel Warfare

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 9923    Accepted Submission(s): 3884


Problem Description
During the War of Resistance Against Japan, tunnel warfare was carried out extensively in the vast areas of north China Plain. Generally speaking, villages connected by tunnels lay in a line. Except the two at the ends, every village was directly connected with two neighboring ones.

Frequently the invaders launched attack on some of the villages and destroyed the parts of tunnels in them. The Eighth Route Army commanders requested the latest connection state of the tunnels and villages. If some villages are severely isolated, restoration of connection must be done immediately!
 

Input
The first line of the input contains two positive integers n and m (n, m ≤ 50,000) indicating the number of villages and events. Each of the next m lines describes an event.

There are three different events described in different format shown below:

D x: The x-th village was destroyed.

Q x: The Army commands requested the number of villages that x-th village was directly or indirectly connected with including itself.

R: The village destroyed last was rebuilt.
 

Output
Output the answer to each of the Army commanders’ request in order on a separate line.
 

Sample Input
  
  
7 9 D 3 D 6 D 5 Q 4 Q 5 R Q 4 R Q 4
 

Sample Output
  
  
1 0 2 4
 

Source


题意:有n个村庄,每个村庄都用地道连接着,分为三种操作,R表示修复最后一个被破坏的村庄,D x表示破话村庄x, Q x表示求包括村庄x的最长连续区间。

思路:线段树的区间合并题目,对于求一个连续最长区间,分三种情况,①是左子树最长连续区间,②是右子树最长连续区间,③是左子树最长右连续区间+右子树最长左连续区间的值,这三种情况取最大值即可。具体可看代码注释,很详细。


AC代码如下:

#include <cstdio>
#include <stack>
#include <cstring>
#include <algorithm>
#define LL long long
using namespace std;

const int maxn = 5e4 + 10;
int n,m,s[maxn],top;
char op[3];
struct node{
	int l,r;    //以rt为根结点的左右区间l表示左端点,r表示右端点 
	int ls,rs,ms;//ls:左起最大连续区间,rs:右起最大连续区间 ms:最大连续区间 
}p[maxn << 2];

void build(int l, int r, int rt){//建树 & 初始化 
	p[rt].l = l; p[rt].r = r;  //以rt为根结点的左右区间[l,r] 
	p[rt].ls = p[rt].ms = p[rt].rs = r - l + 1;   //初始该区间的所有值均为1,故为区间大小 
	if(l != r){
		int m = (l + r) >> 1;
		build(l,m,rt << 1);
		build(m+1,r,rt << 1 | 1);
	}
}

void update(int rt, int x, int flag){//更新x节点的状态 
	if(p[rt].l == p[rt].r){
		if(flag) p[rt].ls = p[rt].ms = p[rt].rs = 1;  //修复 
		else p[rt].ls = p[rt].ms = p[rt].rs = 0;    //破坏 
		return ;
	}
	
	int m = (p[rt].l + p[rt].r) >> 1;
	if(x <= m) update(rt << 1,x,flag);  //要破坏或者修复的点在左子树 
	else update(rt << 1 | 1,x,flag);    //要破坏或者修复的点在右子树 
	
	p[rt].ls = p[rt << 1].ls;     //父节点的左区间最大连续长度等与左子树的, 
	p[rt].rs = p[rt << 1 | 1].rs; //着重分析最后两个if语句 
	p[rt].ms = max(max(p[rt << 1].ms,p[rt << 1 | 1].ms),p[rt << 1].rs + p[rt << 1 | 1].ls);
	//区间的最大连续区间分三种情况:左子树最大连续区间,右子树最大连续区间,左子树右连续+右子树左连续 
	if(p[rt << 1].ls == p[rt << 1].r - p[rt << 1].l + 1) p[rt].ls += p[rt << 1 | 1].ls;
	//左子树的左连续区间长度等于 左子树区间大小,则其父节点的长度应为加上右子树左连续长度 
	if(p[rt << 1 | 1].rs == p[rt << 1 | 1].r - p[rt << 1 | 1].l + 1) p[rt].rs += p[rt << 1].rs;
	//右子树右连续长度等于右子树区间大小,则其父节点的长度为再加上左子树的右连续的长度 
}

int query(int rt, int x){//查询含有节点x的最长连续区间
	//找到x节点或者最长连续区间为0或者区间值全为1 
	if(p[rt].l == p[rt].r || p[rt].ms == 0 || p[rt].ms == p[rt].r - p[rt].l + 1)
		return p[rt].ms;
	int m = (p[rt].l + p[rt].r) >> 1;
	if(x <= m){ //当前结点在左子树 
		//当前节点大于等于左子树右连续区间的左端点值 ,则要再计算上右子树的左连续区间
		if(x >= p[rt << 1].r - p[rt << 1].rs + 1)
			return query(rt << 1,x) + query(rt << 1 | 1,m+1);
		else
			return query(rt << 1,x);
	}
	else{//当前节点小于等于右子树左连续区间的右端点值,则要计算上左子树的右连续区间 
		if(x <= p[rt << 1 | 1].l + p[rt << 1 | 1].ls - 1)
			return query(rt << 1 | 1,x) + query(rt << 1, m);
		else
			return query(rt << 1 | 1,x);  
	}
}

int main(){
	while(~scanf("%d%d",&n,&m)){
		build(1,n,1);
		int num;
		top = 0;
		while(m --){
			scanf("%s",op);
			if(op[0] == 'R'){
				if(num > 0){
					num = s[-- top];
					update(1,num,1);
				}
			}
			else{
				scanf("%d",&num);
				if(op[0] == 'D'){
					s[top ++] = num;
					update(1,num,0);
				}
				else{
					printf("%d\n",query(1,num));
				}
			}
		}
	}
	return 0;
}


内容概要:报告深入分析了2024年国美妆个护跨境电商的发展现状与趋势。首先,概述了国美妆个护行业的总体趋势,指出2023年国内化妆品零售额达4142亿元,同比增长5.1%,出口额为65.1亿美元,同比增长16.7%。产业集群已形成,如上海的“东方美谷”和广州的“白云美湾”。其次,报告详细探讨了国美妆个护外贸趋势,特别是出口市场和品类,广东省在出口占据领先地位,出口额达22.8亿美元,占全国35%。再次,聚焦亚马逊平台,作为跨境电商的龙头,亚马逊拥有超过3.1亿活跃客户,占据美国市场37.6%的份额。报告还提到,2024年Q1亚马逊彩妆和身体护理产品快速占领榜单,基础护肤品类份额被挤占,产品均价略有下跌。最后,强调了品牌建设和渠道控制的重要性,建议商家注重品牌推广,如利用TikTok和线下活动进行营销。 适合人群:从事或关注美妆个护跨境电商的企业主、运营人员、市场营销人员以及相关研究人员。 使用场景及目标:①了解国美妆个护行业的最新发展动态和出口趋势;②掌握亚马逊平台的市场表现和竞争格局;③学习品牌推广和渠道管理的最佳实践,以提高跨境电商的盈利能力。 其他说明:报告引用了大量权威数据和案例,提供了详实的参考依据,帮助从业者更好地把握市场机会并制定有效的营销策略。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值