[洛谷P2184]贪婪大陆

本文介绍了一种使用两棵线段树解决区间地雷问题的方法,通过维护区间内的左端点和右端点数量,实现区间内地雷种类数目的快速查询与更新。采用单点修改和区间查询的方式,算法的时间复杂度为O(m*log2n),适用于动态更新场景。

题目大意:有n个点,每次在l~r之间所有点各加上同一种地雷,或询问某一区间内地雷种数。

解题思路:首先注意是“加上”而不是“覆盖”。

然后我们用两棵线段树(树状数组),一棵维护某一区间内左端点个数,另一棵维护右端点个数。

由于每次只加上一个端点,故为单点修改。

那么如何查询呢?

如果1~r内有a个左端点,则说明最多有a种地雷,如果1~l-1内有b个右端点,则说明a种地雷中,有b种的右端点没有达到l(否则一定在l-1之后)。

那么查询出a和b,然后输出a-b即可。

很明显是区间修改。

时间复杂度$O(m\log_2 n)$。

C++ Code:

#include<cstdio>
#include<cctype>
#include<cstring>
#define N 100005
int n,m,R,ans,d1[N<<2],d2[N<<2];
inline int readint(){
	char c=getchar();
	for(;!isdigit(c);c=getchar());
	int d=0;
	for(;isdigit(c);c=getchar())
	d=(d<<3)+(d<<1)+(c^'0');
	return d;
}
void add1(int l,int r,int o){
	++d1[o];
	if(l!=r){
		int mid=l+r>>1;
		if(R<=mid)add1(l,mid,o<<1);
		if(mid<R)add1(mid+1,r,o<<1|1);
	}
}
void add2(int l,int r,int o){
	++d2[o];
	if(l!=r){
		int mid=l+r>>1;
		if(R<=mid)add2(l,mid,o<<1);
		if(mid<R)add2(mid+1,r,o<<1|1);
	}
}
void query1(int l,int r,int o){
	if(r<=R)ans+=d1[o];else{
		int mid=l+r>>1;
		query1(l,mid,o<<1);
		if(mid<R)query1(mid+1,r,o<<1|1);
	}
}
void query2(int l,int r,int o){
	if(r<=R)ans+=d2[o];else{
		int mid=l+r>>1;
		query2(l,mid,o<<1);
		if(mid<R)query2(mid+1,r,o<<1|1);
	}
}
int main(){
	n=readint(),m=readint();
	memset(d1,0,sizeof d1);
	memset(d2,0,sizeof d2);
	while(m--){
		int opt=readint(),l=readint(),r=readint();
		if(opt==1){
			R=l;
			add1(1,n,1);
			R=r;
			add2(1,n,1);
		}else{
			int Ans=0;
			ans=0;
			R=r;
			query1(1,n,1);
			Ans+=ans;
			ans=0;
			R=l-1;
			if(R)
			query2(1,n,1);
			Ans-=ans;
			printf("%d\n",Ans);
		}
	}
	return 0;
}

转载于:https://www.cnblogs.com/Mrsrz/p/8082331.html

### 关于洛谷 P2207 的题解及相关信息 #### 问题描述 洛谷 P2207 是一道经典的算法竞赛题目,其核心涉及动态规划或贪心策略的应用。虽然未提供具体的题目内容,但从常见的同类型题目来看,该问题可能围绕数组操作、路径优化或其他离散数学模型展开。 以下是基于已有经验对该类问题的通用解答框架: --- #### 动态规划解决方案 如果此问题是关于最短路径或者最优子结构的选择问题,可以采用动态规划方法解决。假设输入是一个二维矩阵 `grid`,目标是从左上角到右下角找到一条路径使得某种代价最小化(如时间和距离)。定义状态转移方程如下[^1]: 设 `dp[i][j]` 表示到达位置 `(i, j)` 的最小成本,则有: ```cpp dp[i][j] = min(dp[i-1][j], dp[i][j-1]) + grid[i][j]; ``` 边界条件为: ```cpp dp[0][j] = sum(grid[0][k]), k from 0 to j; dp[i][0] = sum(grid[k][0]), k from 0 to i; ``` 最终答案存储在 `dp[n-1][m-1]` 中,其中 `n` 和 `m` 分别代表网格的高度和宽度。 完整实现代码如下所示: ```cpp #include <bits/stdc++.h> using namespace std; const int INF = 1e9; int main(){ int n, m; cin >> n >> m; vector<vector<int>> grid(n, vector<int>(m)); for(auto& row : grid){ for(auto& cell : row) cin >> cell; } vector<vector<int>> dp(n, vector<int>(m, INF)); dp[0][0] = grid[0][0]; // 初始化起点 for(int i=0;i<n;i++){ for(int j=0;j<m;j++){ if(i>0) dp[i][j] = min(dp[i][j], dp[i-1][j]+grid[i][j]); if(j>0) dp[i][j] = min(dp[i][j], dp[i][j-1]+grid[i][j]); } } cout << dp[n-1][m-1] << endl; } ``` --- #### 贪心算法思路 对于某些特定场景下的全局最优解寻找过程,也可以尝试利用局部决策来构建整体方案。比如当面临资源分配时,总是优先选取当前剩余量最大的选项直至满足需求为止[^3]。 伪代码展示如下: ```python def greedy_allocation(resources, requirements): resources.sort(reverse=True) result = [] index = 0 while sum(result)<requirements and index<len(resources): result.append(resources[index]) index +=1 return result if sum(result)>=requirements else None ``` 注意这里只是简单示意,并不一定适用于具体实例情况,请根据实际业务逻辑调整细节部分。 --- ### 总结 无论是通过动态规划还是运用贪婪法则处理此类组合优化难题,都需要仔细分析给定约束条件下是否存在重叠子问题以及是否具备无后效性的特点。只有明确了这些前提之后才能有效设计出高效求解办法。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值