QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#792317#7588. Monster Hunterkonata2828AC ✓437ms20260kbC++114.0kb2024-11-29 09:00:442024-11-29 09:00:45

Judging History

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

  • [2024-11-29 09:00:45]
  • 评测
  • 测评结果:AC
  • 用时:437ms
  • 内存:20260kb
  • [2024-11-29 09:00:44]
  • 提交

answer

// Hydro submission #6749123a9592d6097b87ffaa@1732842043107
/*
	先看不在树上的版本 (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],Size[N];
int get(int x){
	return (x==fa[x])?x:(fa[x]=get(fa[x]));
}
void merge(int u,int v){
	u=get(u),v=get(v);
	fa[u]=v;
	Size[v]+=Size[u];
}
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,a,b,Size;
};
bool vis[N];
bool operator < (const P &x,const P &y){  //重载时全都反过来 
	if(x.a<=x.b && y.a>y.b) return false;
	if(x.a>x.b && y.a<=y.b) return true;
	if(x.a<=x.b) return x.a>y.a;
	else return x.b<y.b; 
}
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,a[i],b[i],1});
		}
		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,Size[i]=1,vis[i]=false;	
		
		while(Q.size()){
			P x=Q.top(); Q.pop();
			if(vis[x.u] || x.Size!=Size[x.u]) continue;  //取出过或者不是最新的就不行 
			int u=x.u;
			vis[u]=true;
			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;
			merge(u,Fa);
			if(Fa!=1) Q.push({Fa,a[Fa],b[Fa],Size[Fa]});
		}
		
		printf("%lld\n",a[1]);
	}
	return 0;
}


Details

Tip: Click on the bar to expand more detailed information

Test #1:

score: 100
Accepted
time: 0ms
memory: 7928kb

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: 0
Accepted
time: 437ms
memory: 20080kb

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
383609891
27231993394
19064806867
37194996614
84584890
84657366

result:

ok 10 numbers

Test #3:

score: 0
Accepted
time: 430ms
memory: 20260kb

input:

1109
100
49335125 540429
21327621 30666761
84726139 32583318
62343520 86386375
68371125 80203961
11703807 57711659
4086043 20964787
71845269 8258000
70046842 34257600
86312745 39362281
92327731 31351601
27782858 53379001
51945765 34797724
7197540 99710490
43627335 61003907
256869 8469838
89150549 45...

output:

74012350
485460189
68654921
22821963
702398949
944191
63683983
49851540
539751698
378185590
17649578
153086960
85518043
218934054
40886105
365498548
568650050
115493085
13675680
20327516
19299519
47328093
101160112
314233771
7506569
20797884
140632255
699457438
11257338
71975351
699154224
597663853
...

result:

ok 1109 numbers