LibreOJ #6192. 「美团 CodeM 复赛」城市网络
题目描述
有一个树状的城市网络(即 nnn 个城市由 n−1n-1n−1 条道路连接的连通图),首都为 111 号城市,每个城市售卖价值为 aia_iai 的珠宝。
你是一个珠宝商,现在安排有 qqq 次行程,每次行程为从 uuu 号城市前往 vvv 号城市(走最短路径),保证 vvv 在 uuu 前往首都的最短路径上。
在每次行程开始时,你手上有价值为 ccc 的珠宝(每次行程可能不同),并且每经过一个城市时(包括 uuu 和 vvv),假如那个城市中售卖的珠宝比你现在手上的每一种珠宝都要优秀(价值更高,即严格大于),那么你就会选择购入。
现在你想要对每一次行程,求出会进行多少次购买事件。
输入格式
第一行,两个正整数 n,qn , qn,q。
第二行,nnn 个正整数 aia_iai 描述每个城市售卖的珠宝的价值。
接下来 n−1n-1n−1 行,每行描述一条道路 x,yx , yx,y (1≤x,y≤n1 \leq x , y \leq n1≤x,y≤n),表示有一条连接 xxx 和 yyy 的道路。
接下来 qqq 行,每行描述一次行程 u,v,cu , v , cu,v,c (1≤u,v≤n1 \leq u , v \leq n1≤u,v≤n)。
输出格式
对于每次行程输出一行,为所购买次数。
样例
样例输入
5 4
3 5 1 2 4
1 2
1 3
2 4
3 5
4 2 1
4 2 2
4 2 3
5 1 5
样例输出
2
1
1
0
数据范围与提示
#include<iostream> #include<cstdio> #define maxn 100010 using namespace std; int n,q,w[maxn],num,head[maxn],fa[maxn],dis[maxn],dep[maxn]; struct node{ int to,pre; }e[maxn*2]; void Insert(int from,int to){ e[++num].to=to; e[num].pre=head[from]; head[from]=num; } void dfs(int now,int father){ dep[now]=dep[father]+1; fa[now]=father; for(int i=head[now];i;i=e[i].pre){ int to=e[i].to; if(to==father)continue; dfs(to,now); } } int main(){ scanf("%d%d",&n,&q); for(int i=1;i<=n;i++)scanf("%d",&w[i]); int x,y,z; for(int i=1;i<n;i++){ scanf("%d%d",&x,&y); Insert(x,y);Insert(y,x); } dfs(1,0); while(q--){ scanf("%d%d%d",&x,&y,&z); if(dep[x]<dep[y])swap(x,y); int cnt=0; while(x!=y){ if(w[x]>z)cnt++,z=w[x]; x=fa[x]; } if(w[y]>z)cnt++; printf("%d\n",cnt); } }
#include<iostream> #include<cstdio> #define maxn 200001 using namespace std; int fa[maxn<<1][20]; int num,head[maxn<<1],val[maxn<<1]; int d[maxn<<1],dep[maxn<<1],Dec[maxn<<1]; struct node{ int to,pre; }e[maxn*2]; void Insert(int from,int to){ e[++num].to=to; e[num].pre=head[from]; head[from]=num; } void dfs(int now,int father){ int pos=father; for(int i=18;i>=0;i--) if(fa[pos][i]&&d[fa[pos][i]]<=d[now])pos=fa[pos][i]; if(d[pos]>d[now])fa[now][0]=pos; else fa[now][0]=fa[pos][0]; for(int i=1;fa[fa[now][i-1]][i-1];i++)fa[now][i]=fa[fa[now][i-1]][i-1]; dep[now]=dep[father]+1; for(int i=head[now];i;i=e[i].pre) if(e[i].to!=father)dfs(e[i].to,now); } int main(){ freopen("Cola.txt","r",stdin); int n,q; scanf("%d%d",&n,&q); int x,y,z; for(int i=1;i<=n;i++)scanf("%d",&d[i]); for(int i=1;i<n;i++){ scanf("%d%d",&x,&y); Insert(x,y);Insert(y,x); } int c; for(int i=1;i<=q;i++){ scanf("%d%d%d",&x,&y,&z); Insert(n+i,x);Insert(x,n+i); d[n+i]=z; Dec[i]=y; } dfs(1,0); int ans,pos,t; for(int i=n+1;i<=n+q;i++){ ans=0; pos=i; t=Dec[i-n]; for(int j=18;j>=0;j--) if(dep[fa[pos][j]]>=dep[t]) ans+=1<<j,pos=fa[pos][j]; printf("%d\n",ans); } }