QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#792245#7588. Monster HunterKFCCompile Error//C++983.7kb2024-11-29 08:11:042024-11-29 08:11:06

Judging History

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

  • [2024-11-29 08:11:06]
  • 评测
  • [2024-11-29 08:11:04]
  • 提交

answer

// Hydro submission #674906969592d6097b87f718@1732839063106
/*
	先看不在树上的版本 (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;
}


Details

answer.code: In function ‘void dfs(long long int, long long int)’:
answer.code:54:19: warning: range-based ‘for’ loops only available with ‘-std=c++11’ or ‘-std=gnu++11’ [-Wc++11-extensions]
   54 |         for(int v:G[u]){
      |                   ^
answer.code:54:22: error: forming reference to reference type ‘std::vector<long long int>&’
   54 |         for(int v:G[u]){
      |                      ^
answer.code: In function ‘int main()’:
answer.code:80:32: warning: extended initializer lists only available with ‘-std=c++11’ or ‘-std=gnu++11’ [-Wc++11-extensions]
   80 |                         Q.push({i});
      |                                ^
answer.code:80:31: warning: extended initializer lists only available with ‘-std=c++11’ or ‘-std=gnu++11’ [-Wc++11-extensions]
   80 |                         Q.push({i});
      |                         ~~~~~~^~~~~