gym102201F_Fruit Tree

The meaning of problems

To a weighted tree, repeatedly asked more than half of the number of times appears on the path.

analysis

  • Chairman of the tree dfs order to build and maintain the range is the root to a node in the case of this path.
  • Because the topics are asking the public not an ordinary number, but appear more than half, so the tree can direct the Chairman-half, two sub-trees to see which is more than half of the range, which left subtree, if all half, return -1.
  • Chairman query tree tree tree is different from the sequence of the President, do not subtree difference, but LCA subtree minus twice the sum the corresponding tree, then this will LCA after subtracting the corresponding points to be subtracted Therefore according to LCA determination coupled with the right point.
  • There is a similar topic, UVALive7831.
  • Mo Mo has been the race team team, but finally did not dare come out too easily thought of the river.

Code

#include <bits/stdc++.h>
using namespace std;
const int N=1e6+50;
struct Edge{
    int v,next;
}e[N*2];
int cnt,head[N],a[N];
int n,qs,u,v;
int fa[N][30],d[N],pw[30];
void init(){
    cnt=0;
    memset(head,-1,sizeof(head));
    pw[0]=1;
    for(int i=1;i<=20;i++){
        pw[i]=pw[i-1]*2;
    }
}
void add(int u,int v){
    e[cnt]=Edge{v,head[u]};
    head[u]=cnt++;
    e[cnt]=Edge{u,head[v]};
    head[v]=cnt++;
}
#define mid (l+r)/2
int tr[N],sum[N*30],ls[N*30],rs[N*30],tot;
void update(int pre,int &rt,int l,int r,int v){
    rt=++tot;
    ls[rt]=ls[pre];
    rs[rt]=rs[pre];
    sum[rt]=sum[pre]+1;
    if(l<r){
        if(v<=mid){
            update(ls[pre],ls[rt],l,mid,v);
        }else{
            update(rs[pre],rs[rt],mid+1,r,v);
        }
    }
}
int query(int u,int v,int lca,int l,int r,int k,int lc){
    if(l==r){
        return l;
    }
    int ltmp=sum[ls[u]]+sum[ls[v]]-2*sum[ls[lca]]+(a[lc]>=l && a[lc]<=mid ?1:0);
    int rtmp=sum[rs[u]]+sum[rs[v]]-2*sum[rs[lca]]+(a[lc]>mid && a[lc]<=r ?1:0);
    if(ltmp*2>k){
        return query(ls[u],ls[v],ls[lca],l,mid,k,lc);
    }else if(rtmp*2>k){
        return query(rs[u],rs[v],rs[lca],mid+1,r,k,lc);
    }else{
        return -1;
    }
}
void dfs(int u){
    for(int i=1;pw[i]<=d[u];i++){
        fa[u][i]=fa[fa[u][i-1]][i-1];
    }
    update(tr[fa[u][0]],tr[u],1,n,a[u]);
    for(int i=head[u];i!=-1;i=e[i].next){
        int v=e[i].v;
        if(v==fa[u][0]){
            continue;
        }
        fa[v][0]=u;
        d[v]=d[u]+1;
        dfs(v);
    }
}
int lca(int x,int y){
    if(d[x]<d[y]){
        swap(x,y);
    }
    int tmp=d[x]-d[y];
    for(int i=0;pw[i]<=tmp;i++){
        if(tmp&pw[i]){
            x=fa[x][i];
        }
    }
    if(x==y){
        return x;
    }
    for(int i=19;i>=0;i--){
        if(fa[x][i]!=fa[y][i]){
            x=fa[x][i];
            y=fa[y][i];
        }
    }
    return fa[x][0];
}
int main(){
//    freopen("wo.txt","r",stdin);
    scanf("%d%d",&n,&qs);
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);
    }
    init();
    for(int i=1;i<n;i++){
        scanf("%d%d",&u,&v);
        add(u,v);
    }
    dfs(1);
    while(qs--){
        scanf("%d%d",&u,&v);
        int lc=lca(u,v);
        int len=d[u]+d[v]-2*d[lc]+1;
        int ans=query(tr[u],tr[v],tr[lc],1,n,len,lc);
        printf("%d\n",ans);
    }
    return 0;
}

Guess you like

Origin www.cnblogs.com/zxcoder/p/11599014.html