题目传送门(内部题78)
输入格式
第一行输入两个整数$n,q$,表示节点数和询问数。
第二行输入$n$个整数$w_i$,表示第$i$个点的智商。
第三行至第$n+1$行每行输入两个数$x,y$,表示树上一条边。
第$n+2$行至第$n+q+1$行每行三个数$u,v,c$表示一次探究。(保证$v$是$u$的祖先)
输出格式
输出$q$行,每行两个数表示探究过程中$cwystc$需要努力学习的次数。
样例
见下发文件
数据范围与提示
对于$10\%$的数据:$n\leqslant 1,000$
对于另外$30\%$的数据:家谱树为一条链
对于$100\%$的数据:$n,q,w_i,c\leqslant 100,000$
题解
转化一下题意,就是让我们求从$u$到$v$的$LIS$。
剩下就是码力问题了……
我可能打的比较麻烦,用了主席树和线段树优化……
时间复杂度:$\Theta(n\log n)$。
期望得分:$100$分。
实际得分:$100$分。
代码时刻
#include<bits/stdc++.h> #define L(x) x<<1 #define R(x) x<<1|1 using namespace std; struct rec{int nxt,to;}e[200000]; int head[100001],cnt; int n,q; int w[100001]; int son[100001],size[100001],top[100001],fa[100001],dfn[100001],rk[100001],tim,root[5000001],lson[5000001],rson[5000001],num[5000001],tot; int tr[400001]; void add(int x,int y) { e[++cnt].nxt=head[x]; e[cnt].to=y; head[x]=cnt; } void pushups(int x){num[x]=num[lson[x]]+num[rson[x]];} void pushupm(int x){tr[x]=max(tr[L(x)],tr[R(x)]);} void build(int x,int l,int r) { if(l==r){tr[x]=w[rk[l]];return;} int mid=(l+r)>>1; build(L(x),l,mid); build(R(x),mid+1,r); pushupm(x); } void adds(int &x,int f,int l,int r,int w) { if(!x)x=++tot; if(l==r){num[x]=1;return;} int mid=(l+r)>>1; if(w<=mid) { rson[x]=rson[f]; adds(lson[x],lson[f],l,mid,w); } else adds(rson[x],rson[f],mid+1,r,w); pushups(x); } int asks(int x,int l,int r,int w) { if(!x)return 0; if(w<=l)return num[x]; int mid=(l+r)>>1; if(w<=mid)return asks(lson[x],l,mid,w)+num[rson[x]]; else return asks(rson[x],mid+1,r,w); } int askm(int x,int l,int r,int L,int R) { if(r<L||R<l)return 0; if(L<=l&&r<=R)return tr[x]; int mid=(l+r)>>1; return max(askm(L(x),l,mid,L,R),askm(R(x),mid+1,r,L,R)); } void dfs(int x,int f) { size[x]=1; top[x]=x; adds(root[x],root[f],0,1000000,w[x]); for(int i=head[x];i;i=e[i].nxt) { if(size[e[i].to])continue; fa[e[i].to]=x; dfs(e[i].to,x); size[x]+=size[e[i].to]; if(size[son[x]]<size[e[i].to])son[x]=e[i].to; } } void dfs(int x) { dfn[x]=++tim; rk[tim]=x; if(son[x]) { top[son[x]]=top[x]; dfs(son[x]); } for(int i=head[x];i;i=e[i].nxt) if(!dfn[e[i].to])dfs(e[i].to); } int query(int x,int y,int c) { int now=top[x],mx=c; int res=asks(root[x],0,1000000,c+1); while(now!=top[y]) { mx=max(mx,askm(1,1,n,dfn[now],dfn[x])); x=fa[now]; now=top[x]; } mx=max(mx,askm(1,1,n,dfn[y],dfn[x])); res-=asks(root[fa[y]],0,1000000,mx+1); return res; } int main() { scanf("%d%d",&n,&q); for(int i=1;i<=n;i++)scanf("%d",&w[i]); for(int i=1;i<n;i++) { int u,v; scanf("%d%d",&u,&v); add(u,v);add(v,u); } dfs(1,0); dfs(1); build(1,1,n); while(q--) { int u,v,c; scanf("%d%d%d",&u,&v,&c); printf("%d\n",query(u,v,c)); } return 0; }
rp++
原文地址:https://www.cnblogs.com/wzc521/p/11721940.html
时间: 2024-08-30 14:01:55