P11693 [JRKSJ ExR] 构造字符串使得
P11693 [JRKSJ ExR] 构造字符串使得
题目描述
给你一张
有一初值为
现在先后手总共移动
共有
对于所有数据,保证
保证给出的图无重边、无自环,保证对于任意点
Solution:
说句闲话:
比赛场切了这题,嘻嘻
刚写完就被勒令回学校了,不嘻嘻
至于回学校的原因嘛,竟然是校长要表彰我们这种天天请假不上课的 竞赛拿奖的 😄 。
言归正传:
我们不难发现博弈的总步数其实就三种: 一步,两步和三步。一步的做法很显然,对于走两步以上的:我们来考虑一个子问题:假设你现在是第二步时的 player2,你该如何走使得权值最小。
对于子问题:
如果你此时只有一步了,那么你可以直接走向所有与
如果你在此时还有两步及以上,那么无论 p1 在第3步时选了什么,p2 只需要在第 4 步时选回第 2 步的点就好了。
那么显然 p1 一定会选一个在
所以我们先维护一下每个点的邻居的点权的的最大值
那么原问题的解显然就是与初始点
Code:
#include<bits/stdc++.h> const int N=2e5+5; const int inf=1e9; using namespace std; vector<int> E[N]; int w[3][N],ans[3][N],game[N],mx[N]; int n,m,q; void work() { cin>>n>>m>>q; for(int i=1;i<=n;i++) { w[2][i]=inf;w[1][i]=inf;game[i]=inf; } for(int i=1,x,y;i<=m;i++) { scanf("%d%d",&x,&y); E[x].push_back(y); E[y].push_back(x); w[0][x]=max(w[0][x],y);w[0][y]=max(w[0][y],x); w[1][x]=min(w[1][x],y);w[1][y]=min(w[1][y],x); w[2][x]=min(w[2][x],y);w[2][y]=min(w[2][y],x); } for(int i=1;i<=n;i++) { w[1][i]=max(w[1][i],i); if(w[2][i]==inf)w[2][i]=0; ans[0][i]=w[0][i]; } for(int x=1;x<=n;x++)for(auto y : E[x]) { ans[2][x]=max({ans[2][x],w[2][y],y}); game[x]=min(game[x],max(y,w[0][y])); ans[1][x]=max(ans[1][x],w[1][y]); } for(int x=1;x<=n;x++)for(auto y : E[x])mx[x]=max(mx[x],game[y]); for(int i=1;i<=n;i++)ans[2][i]=max(ans[2][i],mx[i]); for(int i=1,x,k;i<=q;i++) { scanf("%d%d",&x,&k); k= (k>3 ? 3 : k); k--; printf("%d\n",ans[k][x]); } } int main() { //freopen("T1.in","r",stdin);freopen("T1.out","w",stdout); work(); return 0; }