[2020多校联考]树

Solution

(没有定根就非常的离谱,后来告诉根直接就是 \(1\)

先考虑链上怎么做,显然维护一个单调栈,求出第一个比当前数大的位置,然后倍增即可。再放在树上怎么做?依旧维护单调栈,但这次不能暴力地弹掉栈顶元素了,因为这样的复杂度是假的。因为单调栈有单调性,所以直接在单调栈内二分出单调栈弹得不能再弹的位置,然后修改 \(top\),继承答案。搜索回溯的时候再将栈还原即可。对于询问从 \(u\)\(v\) 初始智商为 \(w\) 能学习多少次,因只要 \(pre[u][j]\) 这个人的智商小于等于 \(w\) 就不会产生贡献,所以直接倍增地把这些点都跳过。最后不能跳了,跳到了 \(u'\)。那么 \(pre[u'][0]\) 这个点智商一定比 \(w\) 大,从这个点之后就会产生贡献了。然后再次倍增,只要还在 \(v\) 的子树里。

#include<stdio.h>
#include<algorithm>
using namespace std;
#define N 100007

inline int read(){
    int x=0,flag=1;char c=getchar();
    while(c<'0'||c>'9'){if(c=='-')flag=0;c=getchar();}
    while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+c-48;c=getchar();}
    return flag? x:-x;
}

struct E{
    int next,to;
}e[N<<1];
int head[N],cnt=0;

inline void add(int id,int to){
    e[++cnt]=(E){head[id],to};
    head[id]=cnt;
}

int sta[N],top=0,w[N],n,Q;
int pre[N][18],dep[N],ans[N];

inline bool Cmp(int x,int y){return w[x]>w[y];}
void dfs(int u,int fa_u){
    int lt=top;
    top=lower_bound(sta+1,sta+1+lt,u,Cmp)-sta-1;
    pre[u][0]=sta[top++];
    ans[u]=ans[pre[u][0]]+1;
    for(int i=1;i<=17;i++)
        pre[u][i]=pre[pre[u][i-1]][i-1];
    int lw=sta[top],lpos=top;
    sta[top]=u;
    for(int i=head[u];i;i=e[i].next){
        int v=e[i].to;
        if(v==fa_u) continue;
        dep[v]=dep[u]+1,dfs(v,u);
    }
    top=lt,sta[lpos]=lw;
}

int main(){
    freopen("tree.in","r",stdin);
    freopen("tree.out","w",stdout);
    n=read(),Q=read();
    for(int i=1;i<=n;i++) w[i]=read();
    for(int i=2;i<=n;i++){
        int u=read(),v=read();
        add(u,v),add(v,u);
    }
    dep[1]=1,dfs(1,0);
    while(Q--){
        int u=read(),v=read(),c=read();
        if(w[u]<=c){
            for(int i=17;~i;i--)
                if(pre[u][i]&&w[pre[u][i]]<=c) u=pre[u][i];
            u=pre[u][0];
        }
        if(dep[u]<dep[v]) printf("0\n");
        else{
            int tmp=u;
            for(int i=17;~i;i--)
                if(dep[pre[u][i]]>=dep[v]) u=pre[u][i];
            printf("%d\n",1+ans[tmp]-ans[u]);
        }
    }
}
posted @ 2020-12-01 16:55  Kreap  阅读(85)  评论(0编辑  收藏  举报