51Nod1307 绳子与重物

Problem

有N条绳子编号 0 至 N - 1,每条绳子后面栓了一个重物重量为Wi,绳子的最大负重为Ci。每条绳子或挂在别的绳子下或直接挂在钩子上(编号-1)。如果绳子下所有重物的重量大于绳子的最大负重就会断掉(等于不会断)。依次给出每条绳子的负重Ci、重物的重量Wi以及绳子会挂在之前的哪条绳子的下面,问最多挂多少个绳子而不会出现绳子断掉的情况。

例如下图:

5, 2, -1
3, 3, 0
6, 1, -1
3, 1, 0
3, 2, 3

Solution

从n向1循环,设置一个n的尾指针,每次查询看是否超重,超重就尾指针向前,当前的减去去掉的那个,最后并查集合并到更高位。

Code

#include<stdio.h>
#include<iostream>
using namespace std;
#define io_opt ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define ll long long
int n;
struct E{
	int c,w,p;
}e[50020];
int f[50020];
ll sum[50020];
int find(int x){
	return f[x]==x?x:f[x]=find(f[x]);
}
int main(){
	//io_opt;
	scanf("%d",&n);
	int x,y,z;
	for(int i=1;i<=n;i++){
		f[i]=i;
		scanf("%d%d%d",&x,&y,&z);
		e[i]=(E){x,y,z+1};
	}
	int ans=n;
	for(int i=n;i>=1;i--){
		sum[i]+=e[i].w;
		while(sum[i]>e[i].c){
			sum[find(ans)]-=e[ans].w;
			ans--;
		}
		int u=i,v=e[i].p;
		sum[v]+=sum[u];
		f[u]=v;
	}
	printf("%d
",ans);
	return 0;
}
原文地址:https://www.cnblogs.com/sz-wcc/p/12795879.html