NOIP2024模拟赛10:热烈张扬

NOIP2024模拟赛10:热烈张扬

T1

  • 一句话题意:给定一颗树和两个玩家的起点 \(a,b\) 和各自的移动速度 \(da,db\).问:如果二人均以最优策略移动,问最后谁是赢家(先走到对方当前位置)

  • 标签:LCA,思维,博弈

  • 不妨设 \(a\) 是速度快的,\(b\) 是速度慢的。

  • 结论一:若二者初始距离 \(\le\) 先手的初始速度,则先手第一步就赢.

    除此以外:

  • 结论2:\(a\) 总是可以通过若干步同 \(b\) 调整距离,使得最终 \(a\) 可以跳到 \(b\), 但 \(b\) 跳不到 \(a\).【这很好理解】

  • 结论3:若两者速度相同,平局.

  • 时间复杂度: \(O(T(NlogN+QlogN))\)

#include<bits/stdc++.h>
#define F(i,l,r) for(int i(l);i<=r;++i)
#define G(i,r,l) for(int i(r);i>=l;--i)
using namespace std;
using ll = long long;
char buf[100],*p1=buf,*p2=buf;
inline int gc(){return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,100,stdin),p1==p2)?EOF:*p1++;}
inline int rd(){
	int x=0; char ch;
	while(!isdigit(ch=gc()));
	do x=(x<<3)+(x<<1)+(ch^48); while(isdigit(ch=gc()));
	return x;
}
const int N=2e6+5;
int fa[N][22],dep[N];
int n,q,d,t;
vector<int> G[N];
void ini(int u,int f){
	fa[u][0]=f;
	dep[u]=dep[f]+1;
	F(i,1,20) fa[u][i]=fa[fa[u][i-1]][i-1];
	for(auto v:G[u]){
		if(v==f) continue;
		ini(v,u);
	}
}
int lca(int x,int y){
	if(dep[x]<dep[y]) swap(x,y);
	G(i,20,0) if(dep[fa[x][i]]>=dep[y]) x=fa[x][i];
	if(x==y) return x;
	G(i,20,0) if(fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i];
	return fa[x][0];
}
int calc(int x,int y){
	int p=lca(x,y);
	return dep[x]+dep[y]-2*dep[p];
}
signed main(){
//	freopen("game.in","r",stdin);
//	freopen("game.out","w",stdout);
	d=rd(),t=rd();
	while(t--){
		n=rd(),q=rd();
		F(i,1,n-1){
			int u=rd(),v=rd();
			G[u].emplace_back(v);
			G[v].emplace_back(u);
		}
		ini(1,0);
		while(q--){
			int a=rd(),b=rd(),da=rd(),db=rd();
			int dis=calc(a,b);
			if(da>db) puts("Zayin");
			else if(da==db){
				if(dis<=da) puts("Zayin");
				else puts("Draw");
			}
			else{
				if(dis<=da) puts("Zayin");
				else puts("Ziyin");
			}
		}
		F(i,1,n) {
			G[i].clear();	
		}
	}
	return 0;
} 
  • 总结:
    • 看数据范围这么大,结论应该往简单了猜,否则肯定T掉!
    • 关于 题目条件"最优策略" 的使用:往往是在 "特定一方尽量优的情况下,保证另一方被动中的最优".
posted @ 2024-06-01 17:07  superl61  阅读(14)  评论(0)    收藏  举报