Chairman of the tree learning topics

Count On A Tree

Establishing for each segment tree record ([, u 1] \) \ prefix path in range \ ([L, R] \ ) number of

Calculation query \ (cnt [x] + cnt [y] -cnt [lca] -cnt [fa [lca]] \)

const int N=1e5+10,P=1e9+7;
int n,m;
int s[N*20],ls[N*20],rs[N*20],T[N];
int cnt;


struct Edge{
    int to,nxt;
}e[N<<1];
int head[N],ecnt;
void AddEdge(int u,int v){
    e[++ecnt]=(Edge){v,head[u]};
    head[u]=ecnt;
}
#define erep(u,i) for(int i=head[u];i;i=e[i].nxt)

int fa[N][20];

int ncnt;

void Add(int l,int r,int now,int pre,int x){
    s[now]=s[pre]+1;
    if(l==r) return;
    int mid=(l+r)>>1;
    if(x<=mid) rs[now]=rs[pre],Add(l,mid,ls[now]=++cnt,ls[pre],x);
    else ls[now]=ls[pre],Add(mid+1,r,rs[now]=++cnt,rs[pre],x);
}

int Que(int l,int r,int a,int b,int lca,int f,int k){
    if(l==r) return l;
    int mid=(l+r)>>1;
    int t=s[ls[a]]+s[ls[b]]-s[ls[lca]]-s[ls[f]];
    if(t>=k) return Que(l,mid,ls[a],ls[b],ls[lca],ls[f],k);
    return Que(mid+1,r,rs[a],rs[b],rs[lca],rs[f],k-t);
}

int a[N],b[N],dep[N];

void dfs(int u,int f){
    fa[u][0]=f;
    for(int i=1;(1<<i)<=dep[u];i++) fa[u][i]=fa[fa[u][i-1]][i-1];
    Add(1,ncnt,T[u]=++cnt,T[f],a[u]);
    erep(u,i){
        int v=e[i].to;
        if(v==f) continue;
        dep[v]=dep[u]+1;
        dfs(v,u);
    }
}

int LCA(int x,int y){
    if(dep[x]<dep[y]) swap(x,y);
    for(int i=0,del=dep[x]-dep[y];(1<<i)<=del;i++) if(del&(1<<i)) x=fa[x][i];
    if(x==y) return x;
    drep(i,17,0) if(dep[x]>=(1<<i)){
        if(fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i];
    }
    return fa[x][0];
}




int main(){
    cnt=0;
    n=rd(),m=rd();
    rep(i,1,n) a[i]=b[i]=rd();
    sort(b+1,b+n+1);ncnt=unique(b+1,b+n+1)-b-1;
    rep(i,1,n) a[i]=lower_bound(b+1,b+ncnt+1,a[i])-b;
    rep(i,1,n-1) {
        int u=rd(),v=rd();
        AddEdge(u,v),AddEdge(v,u);
    }
    dfs(1,0);
    rep(i,1,m){
        int x=rd(),y=rd(),k=rd();
        int lca=LCA(x,y);
        int ans=Que(1,ncnt,T[x],T[y],T[lca],T[fa[lca][0]],k);
        printf("%d\n",b[ans]);
    }
}

\[ \ \]

\[ \ \]

\[ \ \]

middle

The weight discrete, build a prefix for each segment tree weights

For the first tree, the leaf nodes of all weights is 1

Each time will be less than the weight of the leaf node is updated to point -1

Segment tree, each point \ ([L, R] \ ) storage section is defined by a

1. and

2. The maximum prefix

3. The maximum suffix

We can define the number of bits of the Central get a conclusion

If the number \ (X \) and less than or equal to its number may be the interval \ ([L, R] \ ) median

In this interval there is greater than or equal to its number is not less than the number in this section is less than its number

I.e. \ (tree [x] \) in \ (sum [L, R] > = 0 \)

Such a segment tree is stored, so that we can ([a, b] \) \ find the maximum and suffixes, in \ ([c, d] \ ) find the largest prefix and, together with this intermediate \ ( [b + 1, c-1 ] \) and the maximum possible

So how do we get this x it?

Dichotomous answer chant

const int N=20005,K=50;
int n;
int a[N],B[N],ncnt;
int T[N];

struct node{
    int lma,rma,s;
}tr[N*K];
int ls[N*K],rs[N*K];
int cnt;

vector <int> V[N];

void Up(node &p,node ls,node rs){
    p.s=ls.s+rs.s;
    p.lma=max(ls.lma,ls.s+rs.lma);
    p.rma=max(rs.rma,ls.rma+rs.s);
}


void Build(int p,int l,int r){
    tr[p]=(node){r-l+1,r-l+1,r-l+1};
    if(l==r) return;
    int mid=(l+r)>>1;
    Build(ls[p]=++cnt,l,mid);
    Build(rs[p]=++cnt,mid+1,r);
}

void Add(int p,int pre,int l,int r,int x){
    tr[p]=tr[pre];
    if(l==r) { tr[p]=(node){-1,-1,-1} ; return; }
    int mid=(l+r)>>1;
    if(x<=mid) rs[p]=rs[pre],Add(ls[p]=++cnt,ls[pre],l,mid,x);
    else ls[p]=ls[pre],Add(rs[p]=++cnt,rs[pre],mid+1,r,x);
    Up(tr[p],tr[ls[p]],tr[rs[p]]);
}


node Que(int p,int l,int r,int ql,int qr){
    if(l==ql&&r==qr) return tr[p];
    int mid=(l+r)>>1;
    if(qr<=mid) return Que(ls[p],l,mid,ql,qr);
    else if(ql>mid) return Que(rs[p],mid+1,r,ql,qr);
    else {
        node ans;
        Up(ans,Que(ls[p],l,mid,ql,mid),Que(rs[p],mid+1,r,mid+1,qr));
        return ans;
    }
}


bool Check(int k,int a,int b,int c,int d){
    int ans=0;
    if(c-1>=b+1) ans+=Que(T[k],1,n,b+1,c-1).s;
    ans+=Que(T[k],1,n,a,b).rma+Que(T[k],1,n,c,d).lma;
    return ans>=0;
}

int main(){
    n=rd();
    rep(i,1,n) a[i]=B[i]=rd();
    sort(B+1,B+n+1),ncnt=unique(B+1,B+n+1)-B-1;
    rep(i,1,n) V[a[i]=lower_bound(B+1,B+ncnt+1,a[i])-B].push_back(i);
    int pre;
    Build(pre=T[1]=++cnt,1,n);
    rep(i,2,ncnt){
        T[i]=T[i-1];
        rep(j,0,V[i-1].size()-1) {
            Add(T[i]=++cnt,pre,1,n,V[i-1][j]);
            pre=T[i];
        }
    }
    pre=0;
    rep(kase,1,rd()){
        int tmp[10];
        rep(j,0,3) tmp[j]=(pre+rd())%n+1;
        sort(tmp,tmp+4);
        int l=1,r=ncnt;
        while(l<=r){
            int mid=(l+r)>>1;
            if(Check(mid,tmp[0],tmp[1],tmp[2],tmp[3])) l=mid+1;
            else r=mid-1;
        }
        printf("%d\n",pre=B[l-1]);
    }
    return 0;
}

Guess you like

Origin www.cnblogs.com/chasedeath/p/11259363.html