Luo Gu P3605 [USACO17JAN] Promotion Counting-- segment tree merger

 

Segment tree merger bare title, in fact, this question can be seen as the number of points for each of the sub-tree point larger than its right value. This question is to see the range of values, know to use dynamic segment tree open point, then we can p array of discrete, each point corresponding to build a range tree line. Finally, starting from the root traversal, backtracking point when there will be boss and subordinate relationships can be merged.

The key is to merge operations:

But it is still well understood, my code does not open a new node, equivalent to merge onto y x, starting from the root down to recursively update, it is quite violent.

The complete code is as follows:

#include<bits/stdc++.h>
using namespace std;
const int maxn=3e6+7;
struct node{
    int nxt;
    int to;
}edge[maxn*2];
int lc[maxn],rc[maxn];
int T;
int a[maxn],p[maxn];
int root[maxn];
struct seg{
    int val;
}tree[maxn*3];
int head[maxn],tot;
int n;
int x;
int neww;
int ans[maxn];
void add(int x,int y){
    edge[++tot].nxt=head[x];
    edge[tot].to=y;
    head[x]=tot;
}
void build(int &node,int l,int r,int x){
    if(!node) node=++T;
    if(l==r){
        tree[node].val++;
        return;
    } 
    int mid=(l+r)>>1;
    if(x<=mid){
        build(lc[node],l,mid,x);
    } 
    else{
        build(rc[node],mid+1,r,x);
    }
    tree[node].val=tree[lc[node]].val+tree[rc[node]].val; 
}
void merge(int &x,int y){
    if(!x||!y){
        x=x+y;
        return;
    }
    tree[x].val=tree[x].val+tree[y].val;
    merge(lc[x],lc[y]);
    merge(rc[x],rc[y]);
}
int query(int node,int l,int r,int v){
    if(l==r) return 0;
    int mid=(l+r)>>1;
    if(v<=mid) return query(lc[node],l,mid,v)+tree[rc[node]].val;
    else return query(rc[node],mid+1,r,v); 
}
void dfs(int x){
    for(int i=head[x];i;i=edge[i].nxt){
        int v=edge[i].to;
        dfs(v);
        merge(root[x],root[v]);//回溯时暴力合并 
    }
    ans[x]=query(root[x],1,neww,p[x]);
}
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%d",&p[i]);
        a[i]=p[i];
    } 
    std::sort(a+1,a+1+n);
    neww=unique(a+1,a+1+n)-a-1;
    for(int i=2;i<=n;i++){
        scanf("%d",&x);
        add(x,i);
    }
    for(int i=1;i<=n;i++){
        p[i]=lower_bound(a+1,a+1+neww,p[i])-a;//离散化 
        build(root[i],1,neww,p[i]);
    }
    dfs(1);
    for(int i=1;i<=n;i++){
        printf("%d\n",ans[i]);
    }
    return 0;
} 
View Code

Guess you like

Origin www.cnblogs.com/LJB666/p/11234726.html