CodeForces - 35E Parade (线段树)

题意:

给你几个矩形,现在问你矩形轮廓线改变的坐标在哪里

思路:

怎样的轮廓线会改变?其实就是当他们的高度改变的时候轮廓线会改变,那么我们离散x坐标,之后维护y的最大值,当y改变的时候我们就记录下当前的横坐标,而纵坐标刚好就是他的高度,其中有一个问题就是 当我们改[1,2]值为1区间和[3,4]值为2区间后 ,我们发现当我们查2的时候他的值是1,而查3的时候他的值是2,但是根据图中画的我们发现他的值其实应该是0才对,但是0刚好被我们所忽略掉了,怎么办呢?我们每次去修改的时候我们就修改他的[L,R-1]区间就好了,还有一个问题就是线段树更新区间最大值的时候不需要用标记数组啊 。。。。傻逼了找了一晚上bug。。。。

代码:

#include <bits/stdc++.h>
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
using namespace std;
const int maxn = 200000 + 10;
struct node
{
	int s,e,h;
}edg[maxn];
int Hash[maxn];
vector<pair<int,int> >V;
struct seg
{
	int tree[maxn<<2];
	void pushdown(int rt)
	{
		if(!tree[rt]) return ;
		tree[rt<<1] = max(tree[rt<<1] , tree[rt]);
		tree[rt<<1|1] = max(tree[rt<<1|1] , tree[rt]);
		tree[rt] = 0;
	}
	void build(int l,int r,int rt)
	{
		tree[rt] = 0 ;
		if(l == r) return ;
		int m = (l+r)>>1;
		build(lson);
		build(rson);
	}
	void update(int L,int R,int val,int l,int r,int rt)
	{
		//printf("%d %d %d %d\n",L,R,l,r);
		if(l >= L && r <= R)
		{
			tree[rt] = max(tree[rt] , val);
			return ;
		}
		pushdown(rt);
		int m = (l+r)>>1;
		if(m >= L) update(L,R,val,lson);
		if(m < R) update(L,R,val,rson);
	}
	void print(int l,int r,int rt)
	{
		if(l == r) {printf("L = %d  R = %d  V = %d \n",l,r,tree[rt]); return ;}
		int m = (l+r)>>1;
		print(lson);
		print(rson);
	}
	int query(int pos,int l,int r,int rt)
	{
		if(l == r) return tree[rt];
		pushdown(rt);
		int m = (l+r)>>1;
		if(m >= pos) return query(pos,lson);
		else return query(pos,rson);
	}
}tree;
int main()
{
//	freopen("input.txt","r",stdin);
//    freopen("output.txt","w",stdout);
	int n;
	scanf("%d",&n);
	int cnt = 0;
	for(int i = 0 ; i < n ; i++)
	{
		scanf("%d%d%d",&edg[i].h,&edg[i].s,&edg[i].e);
		Hash[cnt++] = edg[i].s;
		Hash[cnt++] = edg[i].e; 
	}
	sort(Hash,Hash+cnt);
	cnt = unique(Hash,Hash+cnt) - Hash;
	tree.build(1,cnt,1);
	for(int i = 0 ; i < n ; i++)
	{
		int L = lower_bound(Hash,Hash+cnt,edg[i].s) - Hash + 1;
		int R = lower_bound(Hash,Hash+cnt,edg[i].e) - Hash;
		int p = edg[i].h;
		tree.update(L,R,p,1,cnt,1);
	}
	int now = 0 , last = 0;
	for(int i = 0 ; i < cnt - 1; i++)
	{
		int pos = i+1;
		now = tree.query(pos,1,cnt,1);
		if(now != last)
		{	
			V.push_back(make_pair(Hash[i],last));
			V.push_back(make_pair(Hash[i],now));
		}
		last = now;
	}
	if(now != 0)
	{
		V.push_back(make_pair(Hash[cnt-1],last));
		V.push_back(make_pair(Hash[cnt-1],0));
	}
	cout<<V.size()<<endl;
	for(int i = 0 ; i < V.size() ; i ++) cout<<V[i].first<<" "<<V[i].second<<endl;
}

 

引用\[1\]中提到了一种树形动态规划的方法来解决CodeForces - 982C问题。在这个问题中,subtree指的是子连通块,而不是子树。为了使cnt_white - cnt_black尽可能大,可以使用两次树形动态规划来求解。第一次是自底向上的过程,维护一个dp数组,表示以每个节点为根的子树中的最大连通块。第二次是自顶向下的过程,处理自底向上过程中无法包含的树链所代表的子树。在第二次遍历中,需要维护一个sum变量,用于存储树链所代表的子树的贡献。根据ans\[u\]的正负,决定是否能对相邻的子节点做出贡献。如果ans\[u\]为正,则减去dp\[v\]就是树链所代表的子树的权值。最终,ans\[u\]代表包含节点u在内的子连通块的最大权值。\[1\] 问题: CodeForces - 982C 树形DP是什么问题?如何解决? 回答: CodeForces - 982C是一个树形动态规划问题。在这个问题中,需要求解子连通块的最大权值和,使得cnt_white - cnt_black尽可能大。解决这个问题的方法是使用两次树形动态规划。第一次是自底向上的过程,维护一个dp数组,表示以每个节点为根的子树中的最大连通块。第二次是自顶向下的过程,处理自底向上过程中无法包含的树链所代表的子树。在第二次遍历中,需要维护一个sum变量,用于存储树链所代表的子树的贡献。根据ans\[u\]的正负,决定是否能对相邻的子节点做出贡献。最终,ans\[u\]代表包含节点u在内的子连通块的最大权值。\[1\] #### 引用[.reference_title] - *1* *2* [CodeForces - 1324F Maximum White Subtree(树形dp)](https://blog.csdn.net/qq_45458915/article/details/104831678)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值