Codeforces Round #625题解
Posted encodetalker
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces Round #625题解相关的知识,希望对你有一定的参考价值。
DIV2A
只有第一个人独有的才对他有实际意义,其它的分数均视作1即可。
#include<iostream>
#include<string.h>
#include<string>
#include<stdio.h>
#include<algorithm>
#include<vector>
#include<bitset>
#include<math.h>
#include<stack>
#include<queue>
#include<set>
#include<map>
using namespace std;
typedef long long ll;
typedef long double db;
typedef pair<int,int> pii;
const int N=100000;
const db pi=acos(-1.0);
#define lowbit(x) (x)&(-x)
#define sqr(x) (x)*(x)
#define rep(i,a,b) for (register int i=a;i<=b;i++)
#define per(i,a,b) for (register int i=a;i>=b;i--)
#define go(u,i) for (register int i=head[u];i;i=sq[i].nxt)
#define fir first
#define sec second
#define mp make_pair
#define pb push_back
#define maxd 998244353
#define eps 1e-8
inline int read()
{
int x=0,f=1;char ch=getchar();
while ((ch<'0') || (ch>'9')) {if (ch=='-') f=-1;ch=getchar();}
while ((ch>='0') && (ch<='9')) {x=x*10+(ch-'0');ch=getchar();}
return x*f;
}
namespace My_Math{
#define N 100000
int fac[N+100],invfac[N+100];
int add(int x,int y) {return x+y>=maxd?x+y-maxd:x+y;}
int dec(int x,int y) {return x<y?x-y+maxd:x-y;}
int mul(int x,int y) {return 1ll*x*y%maxd;}
ll qpow(ll x,int y)
{
ll ans=1;
while (y)
{
if (y&1) ans=mul(ans,x);
x=mul(x,x);y>>=1;
}
return ans;
}
int inv(int x) {return qpow(x,maxd-2);}
int C(int n,int m)
{
if ((n<m) || (n<0) || (m<0)) return 0;
return mul(mul(fac[n],invfac[m]),invfac[n-m]);
}
int math_init()
{
fac[0]=invfac[0]=1;
rep(i,1,N) fac[i]=mul(fac[i-1],i);
invfac[N]=inv(fac[N]);
per(i,N-1,1) invfac[i]=mul(invfac[i+1],i+1);
}
#undef N
}
using namespace My_Math;
int n,a[1010],b[1010],c[1010],p[1010];
int main()
{
n=read();
rep(i,1,n) a[i]=read();
rep(i,1,n) b[i]=read();
int ok=0;
rep(i,1,n)
{
if (a[i]) c[i]+=1;
if (b[i]) c[i]+=2;
if (c[i]==1) ok=1;
}
if (!ok) {puts("-1");return 0;}
int rst=0,cnt=0;
rep(i,1,n)
{
if (c[i]>=2) p[i]=1;
if (c[i]==2) rst+=p[i];
if (c[i]==1) cnt++;
}
int ave=rst/cnt;ave++;
rep(i,1,n) if (c[i]==1) p[i]=ave;
cout << ave << endl;
return 0;
}
DIV2B/DIV1A
合法序列的条件移项后得到(c_i+b_{c_i}=c_{i+1}+b_{c_{i+1}}),开个桶维护每个(i+b_i)最大的(i)即可。
#include<iostream>
#include<string.h>
#include<string>
#include<stdio.h>
#include<algorithm>
#include<vector>
#include<bitset>
#include<math.h>
#include<stack>
#include<queue>
#include<set>
#include<map>
using namespace std;
typedef long long ll;
typedef long double db;
typedef pair<int,int> pii;
const int N=100000;
const db pi=acos(-1.0);
#define lowbit(x) (x)&(-x)
#define sqr(x) (x)*(x)
#define rep(i,a,b) for (register int i=a;i<=b;i++)
#define per(i,a,b) for (register int i=a;i>=b;i--)
#define go(u,i) for (register int i=head[u];i;i=sq[i].nxt)
#define fir first
#define sec second
#define mp make_pair
#define pb push_back
#define maxd 998244353
#define eps 1e-8
inline int read()
{
int x=0,f=1;char ch=getchar();
while ((ch<'0') || (ch>'9')) {if (ch=='-') f=-1;ch=getchar();}
while ((ch>='0') && (ch<='9')) {x=x*10+(ch-'0');ch=getchar();}
return x*f;
}
namespace My_Math{
#define N 100000
int fac[N+100],invfac[N+100];
int add(int x,int y) {return x+y>=maxd?x+y-maxd:x+y;}
int dec(int x,int y) {return x<y?x-y+maxd:x-y;}
int mul(int x,int y) {return 1ll*x*y%maxd;}
ll qpow(ll x,int y)
{
ll ans=1;
while (y)
{
if (y&1) ans=mul(ans,x);
x=mul(x,x);y>>=1;
}
return ans;
}
int inv(int x) {return qpow(x,maxd-2);}
int C(int n,int m)
{
if ((n<m) || (n<0) || (m<0)) return 0;
return mul(mul(fac[n],invfac[m]),invfac[n-m]);
}
int math_init()
{
fac[0]=invfac[0]=1;
rep(i,1,N) fac[i]=mul(fac[i-1],i);
invfac[N]=inv(fac[N]);
per(i,N-1,1) invfac[i]=mul(invfac[i+1],i+1);
}
#undef N
}
using namespace My_Math;
const int bas=1000000;
int n,a[bas*4],b[bas*4];
ll f[600600];
int main()
{
n=read();
rep(i,1,n) a[i]=read();
rep(i,1,n)
{
int now=i-a[i]+bas;
f[i]=f[b[now]]+a[i];
b[now]=i;
}
ll ans=0;
rep(i,1,n) ans=max(ans,f[i]);
cout << ans;
return 0;
}
DIV2C
考虑一下当前可删的字典序最大字符,与它相邻的两个字符肯定不会因为它才能被删。于是每次删最大的字符的贪心是正确的。
#include<iostream>
#include<string.h>
#include<string>
#include<stdio.h>
#include<algorithm>
#include<vector>
#include<bitset>
#include<math.h>
#include<stack>
#include<queue>
#include<set>
#include<map>
using namespace std;
typedef long long ll;
typedef long double db;
typedef pair<int,int> pii;
const int N=100000;
const db pi=acos(-1.0);
#define lowbit(x) (x)&(-x)
#define sqr(x) (x)*(x)
#define rep(i,a,b) for (register int i=a;i<=b;i++)
#define per(i,a,b) for (register int i=a;i>=b;i--)
#define go(u,i) for (register int i=head[u];i;i=sq[i].nxt)
#define fir first
#define sec second
#define mp make_pair
#define pb push_back
#define maxd 998244353
#define eps 1e-8
inline int read()
{
int x=0,f=1;char ch=getchar();
while ((ch<'0') || (ch>'9')) {if (ch=='-') f=-1;ch=getchar();}
while ((ch>='0') && (ch<='9')) {x=x*10+(ch-'0');ch=getchar();}
return x*f;
}
namespace My_Math{
#define N 100000
int fac[N+100],invfac[N+100];
int add(int x,int y) {return x+y>=maxd?x+y-maxd:x+y;}
int dec(int x,int y) {return x<y?x-y+maxd:x-y;}
int mul(int x,int y) {return 1ll*x*y%maxd;}
ll qpow(ll x,int y)
{
ll ans=1;
while (y)
{
if (y&1) ans=mul(ans,x);
x=mul(x,x);y>>=1;
}
return ans;
}
int inv(int x) {return qpow(x,maxd-2);}
int C(int n,int m)
{
if ((n<m) || (n<0) || (m<0)) return 0;
return mul(mul(fac[n],invfac[m]),invfac[n-m]);
}
int math_init()
{
fac[0]=invfac[0]=1;
rep(i,1,N) fac[i]=mul(fac[i-1],i);
invfac[N]=inv(fac[N]);
per(i,N-1,1) invfac[i]=mul(invfac[i+1],i+1);
}
#undef N
}
using namespace My_Math;
int n;
char s[120];
int main()
{
n=read();
scanf("%s",s+1);
int ans=0;
while (1)
{
int p=0;
rep(i,1,n)
{
if ((s[i]==s[i-1]+1) || (s[i]==s[i+1]+1))
{
if (!p) p=i;
else if (s[p]<s[i]) p=i;
}
}
if (!p) break;ans++;
rep(i,p+1,n) s[i-1]=s[i];
s[n]=' ';n--;
}
cout << ans;
return 0;
}
DIV2D/DIV1B
建返图之后建以(p_k)为源的最短路图,接下来对每个(p_i)分类讨论。
若(p_i)无法到达(p_{i+1}),那么这一步一定会带来一次( m{rebuild}).
若(p_i)能到达多个点,其中有一个是(p_i), 那么这一步可能会带来一次( m{rebuild}), 即只会对最大值有贡献。
#include<iostream>
#include<string.h>
#include<string>
#include<stdio.h>
#include<algorithm>
#include<vector>
#include<bitset>
#include<math.h>
#include<stack>
#include<queue>
#include<set>
#include<map>
using namespace std;
typedef long long ll;
typedef long double db;
typedef pair<int,int> pii;
const int N=100000;
const db pi=acos(-1.0);
#define lowbit(x) (x)&(-x)
#define sqr(x) (x)*(x)
#define rep(i,a,b) for (register int i=a;i<=b;i++)
#define per(i,a,b) for (register int i=a;i>=b;i--)
#define go(u,i) for (register int i=head[u];i;i=sq[i].nxt)
#define fir first
#define sec second
#define mp make_pair
#define pb push_back
#define maxd 998244353
#define eps 1e-8
inline int read()
{
int x=0,f=1;char ch=getchar();
while ((ch<'0') || (ch>'9')) {if (ch=='-') f=-1;ch=getchar();}
while ((ch>='0') && (ch<='9')) {x=x*10+(ch-'0');ch=getchar();}
return x*f;
}
namespace My_Math{
#define N 100000
int fac[N+100],invfac[N+100];
int add(int x,int y) {return x+y>=maxd?x+y-maxd:x+y;}
int dec(int x,int y) {return x<y?x-y+maxd:x-y;}
int mul(int x,int y) {return 1ll*x*y%maxd;}
ll qpow(ll x,int y)
{
ll ans=1;
while (y)
{
if (y&1) ans=mul(ans,x);
x=mul(x,x);y>>=1;
}
return ans;
}
int inv(int x) {return qpow(x,maxd-2);}
int C(int n,int m)
{
if ((n<m) || (n<0) || (m<0)) return 0;
return mul(mul(fac[n],invfac[m]),invfac[n-m]);
}
int math_init()
{
fac[0]=invfac[0]=1;
rep(i,1,N) fac[i]=mul(fac[i-1],i);
invfac[N]=inv(fac[N]);
per(i,N-1,1) invfac[i]=mul(invfac[i+1],i+1);
}
#undef N
}
using namespace My_Math;
struct edgenode{int u,v;}edge[200200];
struct node{int to,nxt;}sq[200200];
int all=0,head[200200];
void addedge(int u,int v){all++;sq[all].to=v;sq[all].nxt=head[u];head[u]=all;}
int d[200200],dis[200200],n,m,k,p[200200];
bool vis[200200],must[200200];
vector<int> sq2[200200];
struct hnode{int u,dis;};
bool operator <(hnode p,hnode q) {return p.dis>q.dis;}
priority_queue<hnode> q;
void dij(int st)
{
//cout << "start " << st << endl;
memset(dis,0x3f,sizeof(dis));
dis[st]=0;q.push((hnode){st,0});
while (!q.empty())
{
int u=q.top().u;q.pop();
if (vis[u]) continue;vis[u]=1;
go(u,i)
{
int v=sq[i].to;
if (dis[v]>dis[u]+1)
{
dis[v]=dis[u]+1;
if (!vis[v]) q.push((hnode){v,dis[v]});
}
}
}
//rep(i,1,n) cout << dis[i] << " ";cout << endl;
rep(i,1,m)
{
int u=edge[i].u,v=edge[i].v;
if (dis[v]+1==dis[u]) sq2[u].pb(v);
}
rep(i,1,n) d[i]=(int)sq2[i].size();
rep(i,1,k-1)
{
int u=p[i];must[i]=1;
rep(j,0,d[u]-1)
if (sq2[u][j]==p[i+1]) must[i]=0;
}
}
int main()
{
n=read();m=read();
rep(i,1,m)
{
edge[i].u=read();edge[i].v=read();
addedge(edge[i].v,edge[i].u);
}
k=read();
rep(i,1,k) p[i]=read();
dij(p[k]);
int cnt=0,mx=0,mn=0;
rep(i,1,k-1)
{
if (must[i]) cnt++;
else if (d[p[i]]>1) mx++;
}
mx+=cnt;mn+=cnt;
cout << mn << " " << mx << endl;
return 0;
}
DIV2E/DIV1C
从小到大枚举武器,同时维护每个防具的答案。
怪物按照防御值排序,随着武器的枚举而计算贡献,发现每个怪物对防具的贡献都是后缀加的形式,直接线段树维护即可。
#include<iostream>
#include<string.h>
#include<string>
#include<stdio.h>
#include<algorithm>
#include<vector>
#include<bitset>
#include<math.h>
#include<stack>
#include<queue>
#include<set>
#include<map>
using namespace std;
typedef long long ll;
typedef long double db;
typedef pair<int,int> pii;
const int N=100000;
const db pi=acos(-1.0);
#define lowbit(x) (x)&(-x)
#define sqr(x) (x)*(x)
#define rep(i,a,b) for (register int i=a;i<=b;i++)
#define per(i,a,b) for (register int i=a;i>=b;i--)
#define go(u,i) for (register int i=head[u];i;i=sq[i].nxt)
#define fir first
#define sec second
#define mp make_pair
#define pb push_back
#define maxd 998244353
#define eps 1e-8
inline int read()
{
int x=0,f=1;char ch=getchar();
while ((ch<'0') || (ch>'9')) {if (ch=='-') f=-1;ch=getchar();}
while ((ch>='0') && (ch<='9')) {x=x*10+(ch-'0');ch=getchar();}
return x*f;
}
namespace My_Math{
#define N 100000
int fac[N+100],invfac[N+100];
int add(int x,int y) {return x+y>=maxd?x+y-maxd:x+y;}
int dec(int x,int y) {return x<y?x-y+maxd:x-y;}
int mul(int x,int y) {return 1ll*x*y%maxd;}
ll qpow(ll x,int y)
{
ll ans=1;
while (y)
{
if (y&1) ans=mul(ans,x);
x=mul(x,x);y>>=1;
}
return ans;
}
int inv(int x) {return qpow(x,maxd-2);}
int C(int n,int m)
{
if ((n<m) || (n<0) || (m<0)) return 0;
return mul(mul(fac[n],invfac[m]),invfac[n-m]);
}
int math_init()
{
fac[0]=invfac[0]=1;
rep(i,1,N) fac[i]=mul(fac[i-1],i);
invfac[N]=inv(fac[N]);
per(i,N-1,1) invfac[i]=mul(invfac[i+1],i+1);
}
#undef N
}
using namespace My_Math;
struct node{int v,c;}atk[200200],def[200200],atk1[200200],def1[200200];
bool operator <(node p,node q)
{
return ((p.v<q.v) || ((p.v==q.v) && (p.c<q.c)));
}
struct mnode{int a,d,z;}mon[200200];
bool operator <(mnode p,mnode q) {return p.d<q.d;}
int n,m,p,x[200200];
ll tag[4004000],seg[4004000];
void build(int id,int l,int r)
{
if (l==r) {seg[id]=-def[l].c;return;}
int mid=(l+r)>>1;
build(id<<1,l,mid);build(id<<1|1,mid+1,r);
seg[id]=max(seg[id<<1],seg[id<<1|1]);
}
void pushdown(int id)
{
if (tag[id])
{
seg[id<<1]+=tag[id];seg[id<<1|1]+=tag[id];
tag[id<<1]+=tag[id];tag[id<<1|1]+=tag[id];
tag[id]=0;
}
}
void modify(int id,int l,int r,int ql,int qr,int val)
{
if ((l>=ql) && (r<=qr))
{
seg[id]+=val;tag[id]+=val;
return;
}
pushdown(id);
int mid=(l+r)>>1;
if (ql<=mid) modify(id<<1,l,mid,ql,qr,val);
if (qr>mid) modify(id<<1|1,mid+1,r,ql,qr,val);
seg[id]=max(seg[id<<1],seg[id<<1|1]);
}
int main()
{
n=read();m=read();p=read();
rep(i,1,n) {atk1[i].v=read();atk1[i].c=read();}
rep(i,1,m) {def1[i].v=read();def1[i].c=read();}
sort(def1+1,def1+1+m);
sort(atk1+1,atk1+1+n);
int tp=0;
memset(seg,-0x3f,sizeof(seg));
rep(i,1,n)
if (atk1[i].v!=atk[tp].v) atk[++tp]=atk1[i];
n=tp;tp=0;
rep(i,1,m)
if (def1[i].v!=def[tp].v) def[++tp]=def1[i];
m=tp;
rep(i,1,p)
{
mon[i].d=read();mon[i].a=read();mon[i].z=read();
}
rep(i,1,m) x[i]=def[i].v;
//cout << endl;
//rep(i,1,m) cout << x[i] << " " << def[i].c << endl;
sort(mon+1,mon+1+p);
build(1,1,m);
ll ans=-1e18;int pos=1;
rep(i,1,n)
{
while ((pos<=p) && (atk[i].v>mon[pos].d))
{
int p1=upper_bound(x+1,x+1+m,mon[pos].a)-x;
if (mon[pos].a<x[m])
modify(1,1,m,p1,m,mon[pos].z);
pos++;
}
ans=max(ans,seg[1]-atk[i].c);
}
cout << ans;
return 0;
}
DIV2F/DIV1D
发现每个操作的可以将一个(0)向前或向后移(2)位,也就是不会改变其下标的奇偶性。
同时又注意到形如(00)这样的串,两个(0)都互相无法越过对方。
所以判断两个子串是否能变成一致的条件就是:两个子串中(0)的下标的奇偶性均相同。
把这个变成一个字符串的形式,直接上哈希就行了(反正没人来得及叉)
#include<iostream>
#include<string.h>
#include<string>
#include<stdio.h>
#include<algorithm>
#include<vector>
#include<bitset>
#include<math.h>
#include<stack>
#include<queue>
#include<set>
#include<map>
using namespace std;
typedef long long ll;
typedef long double db;
typedef pair<int,int> pii;
const int N=200000+100;
const db pi=acos(-1.0);
#define lowbit(x) (x)&(-x)
#define sqr(x) (x)*(x)
#define rep(i,a,b) for (register int i=a;i<=b;i++)
#define per(i,a,b) for (register int i=a;i>=b;i--)
#define go(u,i) for (register int i=head[u];i;i=sq[i].nxt)
#define fir first
#define sec second
#define mp make_pair
#define pb push_back
#define maxd 1000000009
#define eps 1e-8
#define bas 233
inline int read()
{
int x=0,f=1;char ch=getchar();
while ((ch<'0') || (ch>'9')) {if (ch=='-') f=-1;ch=getchar();}
while ((ch>='0') && (ch<='9')) {x=x*10+(ch-'0');ch=getchar();}
return x*f;
}
ll hsh[N][2],pw[N];
int n,q,cnt[N];
char s[N];
ll query(int l,int r,int op)
{
ll now=hsh[r][op]-hsh[l-1][op]*pw[cnt[r]-cnt[l-1]];
return (now%maxd+maxd)%maxd;
}
int main()
{
n=read();
scanf("%s",s+1);
hsh[0][0]=hsh[1][0]=1;
rep(i,1,n)
{
hsh[i][0]=hsh[i-1][0];hsh[i][1]=hsh[i-1][1];cnt[i]=cnt[i-1];
if (s[i]=='0')
{
hsh[i][0]=(hsh[i][0]*bas+'0'+(i&1))%maxd;
hsh[i][1]=(hsh[i][1]*bas+'0'+((i&1)^1))%maxd;
cnt[i]++;
}
}
pw[0]=1;
rep(i,1,n) pw[i]=pw[i-1]*bas%maxd;
q=read();
while (q--)
{
int l1=read(),l2=read(),len=read();
int r1=l1+len-1,r2=l2+len-1;
if (query(l1,r1,l1&1)==query(l2,r2,l2&1)) puts("Yes");
else puts("No");
}
return 0;
}
DIV1F
把虚树已经写在脸上的题目(但是我早就忘记怎么写了)
发现虚树上每条路径上被隐去的点必然会被染上同一种病毒,于是虚树的合法性就有了,接下来写一个多源dijkstra就好了。
#include<iostream>
#include<string.h>
#include<string>
#include<stdio.h>
#include<algorithm>
#include<vector>
#include<bitset>
#include<math.h>
#include<stack>
#include<queue>
#include<set>
#include<map>
using namespace std;
typedef long long ll;
typedef long double db;
typedef pair<int,int> pii;
const int N=200000+100;
const db pi=acos(-1.0);
#define lowbit(x) (x)&(-x)
#define sqr(x) (x)*(x)
#define rep(i,a,b) for (register int i=a;i<=b;i++)
#define per(i,a,b) for (register int i=a;i>=b;i--)
#define go(u,i) for (register int i=head[u];i;i=sq[i].nxt)
#define fir first
#define sec second
#define mp make_pair
#define pb push_back
#define maxd 998244353
#define eps 1e-8
inline int read()
{
int x=0,f=1;char ch=getchar();
while ((ch<'0') || (ch>'9')) {if (ch=='-') f=-1;ch=getchar();}
while ((ch>='0') && (ch<='9')) {x=x*10+(ch-'0');ch=getchar();}
return x*f;
}
namespace My_Math{
#define N 100000
int fac[N+100],invfac[N+100];
int add(int x,int y) {return x+y>=maxd?x+y-maxd:x+y;}
int dec(int x,int y) {return x<y?x-y+maxd:x-y;}
int mul(int x,int y) {return 1ll*x*y%maxd;}
ll qpow(ll x,int y)
{
ll ans=1;
while (y)
{
if (y&1) ans=mul(ans,x);
x=mul(x,x);y>>=1;
}
return ans;
}
int inv(int x) {return qpow(x,maxd-2);}
int C(int n,int m)
{
if ((n<m) || (n<0) || (m<0)) return 0;
return mul(mul(fac[n],invfac[m]),invfac[n-m]);
}
int math_init()
{
fac[0]=invfac[0]=1;
rep(i,1,N) fac[i]=mul(fac[i-1],i);
invfac[N]=inv(fac[N]);
per(i,N-1,1) invfac[i]=mul(invfac[i+1],i+1);
}
#undef N
}
using namespace My_Math;
struct sqnode{int to,nxt;}sq[N<<1];
int all=0,head[N];
int tp[N],fa[N],siz[N],dep[N],tim=0,dfn[N],son[N];
int n,m,k,ans[N],ask[N];
struct virus{int id,spd;}vir[N];
void addedge(int u,int v)
{
all++;sq[all].nxt=head[u];sq[all].to=v;head[u]=all;
}
void dfs1(int u,int fu)
{
fa[u]=fu;siz[u]=1;dep[u]=dep[fu]+1;dfn[u]=(++tim);
go(u,i)
{
int v=sq[i].to;
if (v==fu) continue;
dfs1(v,u);siz[u]+=siz[v];
if (siz[v]>siz[son[u]]) son[u]=v;
}
}
void dfs2(int u,int tpu)
{
tp[u]=tpu;
if (son[u]) dfs2(son[u],tpu);
go(u,i)
{
int v=sq[i].to;
if ((v==fa[u]) || (v==son[u])) continue;
dfs2(v,v);
}
}
int query(int u,int v)
{
while (tp[u]!=tp[v])
{
if (dep[tp[u]]<dep[tp[v]]) swap(u,v);
u=fa[tp[u]];
}
if (dep[u]>dep[v]) swap(u,v);
return u;
}
vector<pii> tr[N];
int sta[N];
vector<int> used;
void addedgetr(int u,int v)
{
int dis=abs(dep[u]-dep[v]);
//cout << "add " << u << " " << v << " " << dis << endl;
tr[u].pb(mp(v,dis));tr[v].pb(mp(u,dis));
}
bool cmp(int u,int v) {return dfn[u]<dfn[v];}
void virtual_tree(vector<int> p)
{
sort(p.begin(),p.end(),cmp);
int len=unique(p.begin(),p.end())-p.begin();
int tp=0;used.clear();
//cout << "vtree ";
//rep(i,0,len-1) cout << p[i] << " ";cout << endl;
rep(i,0,len-1)
{
int u=p[i];used.pb(u);
if (!tp) {sta[++tp]=u;continue;}
int lca=query(u,sta[tp]);
while ((tp) && (dep[sta[tp-1]]>=dep[lca])) {addedgetr(sta[tp-1],sta[tp]);tp--;}
if (sta[tp]!=lca) {addedgetr(sta[tp],lca);sta[tp]=lca;used.pb(lca);}
sta[++tp]=u;
}
while (tp>1)
{
addedgetr(sta[tp],sta[tp-1]);
tp--;
}
}
struct hnode{int dis,tim,u,vid;};
bool operator <(hnode p,hnode q)
{
if (p.tim==q.tim) return p.vid>q.vid;
else return p.tim>q.tim;
}
priority_queue<hnode> q;
void dij()
{
rep(i,1,m)
q.push((hnode){0,0,vir[i].id,i});
while (!q.empty())
{
hnode now=q.top();q.pop();
if (ans[now.u]) continue;
ans[now.u]=now.vid;int len=tr[now.u].size();
rep(i,0,len-1)
{
int v=tr[now.u][i].fir,d=tr[now.u][i].sec;
if (!ans[v])
{
int t=(now.dis+d-1)/vir[now.vid].spd+1;
q.push((hnode){now.dis+d,t,v,now.vid});
}
}
}
}
int main()
{
n=read();
rep(i,1,n-1)
{
int u=read(),v=read();
addedge(u,v);addedge(v,u);
}
dfs1(1,0);dfs2(1,1);
int q=read();
while (q--)
{
m=read();k=read();
vector<int> p;p.clear();
rep(i,1,m)
{
vir[i].id=read();vir[i].spd=read();
p.pb(vir[i].id);
}
rep(i,1,k)
{
ask[i]=read();p.pb(ask[i]);
}
virtual_tree(p);
dij();
//printf("answer ");
rep(i,1,k) printf("%d ",ans[ask[i]]);puts("");
int len=used.size();
rep(i,0,len-1) {ans[used[i]]=0;tr[used[i]].clear();}
}
return 0;
}
以上是关于Codeforces Round #625题解的主要内容,如果未能解决你的问题,请参考以下文章
Codeforces Round #625 Div. 2 D E
Codeforces Round #625 (Div. 2, based on Technocup 2020 Final Round) A. Contest for Robots(思维题)
Codeforces Round #625 (Div. 2, based on Technocup 2020 Final Round)
Codeforces Round #625 (Div. 2, based on Technocup 2020 Final Round) 简单解析