QOJ.ac

QOJ

ID题目提交者结果用时内存语言文件大小提交时间测评时间
#792246#7588. Monster HunterKFCWA 320ms16756kbC++143.7kb2024-11-29 08:11:172024-11-29 08:11:17

Judging History

你现在查看的是最新测评结果

  • [2024-11-29 08:11:17]
  • 评测
  • 测评结果:WA
  • 用时:320ms
  • 内存:16756kb
  • [2024-11-29 08:11:17]
  • 提交

answer

// Hydro submission #674906a49592d6097b87f724@1732839076415
/*
	先看不在树上的版本 (P4025):
	有 n 个怪兽,每一个怪兽有两个属性 a,b。
	a 表示打败他需要扣掉 a 的体力,b 表示打败之后加的体力。
	可以任意钦定挑战顺序。
	
	我们先确定挑战顺序:
	把它分成两类考虑,一种是 a<=b 打完之后加血,一种是 a>b 打完之后扣血。
	我肯定是先打加血的,再打扣血的。
	1. 在加血的内部,我肯定是按照 a 升序排,这样可以最大可能的保证我能活着。
	2. 在扣血的内部,我们考虑正难则反,我们正着考虑是不断地扣血,那倒着考虑就是不断加血,
	根据我们 1. 中的结论,应该按照 a'(其实是原来的 b) 升序排,那再反回来过来就是按照 b 降序排。
	如果你一定要正着考虑的话也不是不行,假设现在有两个怪兽 (ai,bi),(aj,bj)(ai>bi,aj>bj,bj>bi)。
	1. ai>aj:我先放 (aj,bj) 一定不劣,因为不仅扣的少还加的多。
	2. ai<aj:此时我如果先去打 (ai,bi) 是可行的话,说明此时的血量 x>ai,但因为后面 x 会变小,所以当去打 (aj,bj) 时的血量 x'<x,但是如果 x'>aj,
	那么 x 也一定 >aj,所以我先打 (aj,bj) 也一定可行,并且更优。
	
	按照这个排序即可。 
	
	放到这题里面,因为他还给你钦定了要满足祖先关系所以不能这么排。
	但是,注意到如果一个点 u 的优先级比 fa 高,那么当 fa 被选的时候,我去立刻选 u 一定不劣。
	那我们就可以直接把 u 和 fa 合并成一个新的点。
	我们不断从优先队列中取出优先级最高的点和他的父亲合并,最后的根节点的 a 就是答案。
	现在我们只需要确定合并后的节点的 a,b 值是什么:
	我们需要保证两个事情:
	1. 原来会死的在合并之后依旧会死
	2. 最后加的/扣的血量保持不变
	会发现在取 u 和 fa 这两个点的过程中,扣血量的最大值是 max(a[fa],a[fa]-b[fa]+a[u])。
	我们把这个当作合并后的节点的 a,把 max(a[fa],a[fa]-b[fa]+a[u])+b[fa]+b[u]-a[fa]-a[u] 作为合并后节点的 b 就行了。 
	
	用并查集维护即可。 
*/
#include<bits/stdc++.h>
#define int long long 
using namespace std;
const int N=1e5+5;
inline int read(){
    int w = 1, s = 0;
    char c = getchar();
    for (; c < '0' || c > '9'; w *= (c == '-') ? -1 : 1, c = getchar());
    for (; c >= '0' && c <= '9'; s = 10 * s + (c - '0'), c = getchar());
    return s * w;
}
int n,a[N],b[N];
vector<int> G[N];
void add(int u,int v){G[u].push_back(v);}
int f[N],fa[N];
int get(int x){
	return (x==fa[x])?x:(fa[x]=get(fa[x]));
}
void dfs(int u,int fa){
	f[u]=fa;
	for(int v:G[u]){
		if(v==fa) continue;
		dfs(v,u);
	}
}
struct P{
	int u;
};
bool operator < (const P &A,const P &B){  //重载时全都反过来 
	int x=A.u,y=B.u;
	if(a[x]<=b[x] && a[y]>b[y]) return false;
	if(a[x]>b[x] && a[y]<=b[y]) return true;
	if(a[x]<=b[x]) return a[x]>a[y];
	else return b[x]<b[y]; 
}
priority_queue<P> Q;
signed main(){
//	freopen("tree.in","r",stdin);
//	freopen("tree.out","w",stdout);
	int T=read();
	while(T--){
		n=read();
		a[1]=b[1]=0;
		for(int i=1;i<=n;i++) G[i].clear();
		for(int i=2;i<=n;i++){
			a[i]=read(),b[i]=read();
			Q.push({i});
		}
		for(int i=1;i<n;i++){
			int u=read(),v=read();
			add(u,v),add(v,u);
		}
		
		dfs(1,0);
		
		for(int i=1;i<=n;i++) fa[i]=i;	
		
		while(Q.size()){
			int u=Q.top().u; Q.pop();
			int Fa=get(f[u]);
			int ta=max(a[Fa],a[Fa]-b[Fa]+a[u]),tb=max(a[Fa],a[Fa]-b[Fa]+a[u])+b[Fa]+b[u]-a[Fa]-a[u];
			a[Fa]=ta,b[Fa]=tb;
			fa[u]=Fa;
		}
		
		printf("%lld\n",a[1]);
	}
	return 0;
}


详细

Test #1:

score: 100
Accepted
time: 1ms
memory: 7956kb

input:

1
4
2 6
5 4
6 2
1 2
2 3
3 4

output:

3

result:

ok 1 number(s): "3"

Test #2:

score: -100
Wrong Answer
time: 320ms
memory: 16756kb

input:

10
50000
112474 198604
847262 632597
871374 962220
971398 284540
10360 695245
43233 569941
64019 203468
598469 997911
41841 657552
333198 936119
546370 180011
58831 901040
959767 396595
710441 277461
429299 209831
494164 138327
393982 581911
993164 617488
108113 160310
55841 611360
301395 291074
149...

output:

63495498
541156749
191617241
177090559
630213926
27231993394
19064806867
37194996614
84584890
84657366

result:

wrong answer 5th numbers differ - expected: '383609891', found: '630213926'