Count on a tree The K-th smallest weight on the road (u, v) on the tree (chairman tree + tree section lca

topic link

The meaning of the title: 
It is to find the K-th smallest weight on the road (u, v) on the tree

Problem- solving ideas: 
First of all, we can use the chairman tree to solve the problem of finding the Kth smallest, no problem, 
but for a tree structure, we need to convert it into linear, and then we need tree section to do it.

Then consider how to maintain the kth value on the chain, and 
find that it cannot be maintained if the tree section is calculated, 
because the path of (u, v) may be in many chains, so the kth value cannot be calculated for each, which is obviously wrong. what,

Then we know that the chairman tree actually maintains a prefix and

Then we can establish a prefix sum from each node to the root node, and then we can find the Kth value from any node to the root node, 
then according to the properties of the chairman tree, we can calculate the Kth value on the path of (u, v)
Just change it a little when you query 

cnt = sum[ls[u]]+sum[ls[v]]-sum[ls[lca(u,v)]]-sum[ls[fa[lca(u,v)]]];
 

///                 .-~~~~~~~~~-._       _.-~~~~~~~~~-.
///             __.'              ~.   .~              `.__
///           .'//                  \./                  \\`.
///        .'//                     |                     \\`.
///       .'// .-~"""""""~~~~-._     |     _,-~~~~"""""""~-. \\`.
///     .'//.-"                 `-.  |  .-'                 "-.\\`.
///   .'//______.============-..   \ | /   ..-============.______\\`.
/// .'______________________________\|/______________________________`.
#pragma GCC optimize("Ofast")
#pragma comment(linker, "/STACK:102400000,102400000")
#pragma GCC target(sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx) 
#include<bits/stdc++.h>
using namespace std;

#define pi acos(-1)
#define s_1(x) scanf("%d",&x)
#define s_2(x,y) scanf("%d%d",&x,&y)
#define s_3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define s_4(x,y,z,X) scanf("%d%d%d%d",&x,&y,&z,&X)
#define S_1(x) scan_d(x)
#define S_2(x,y) scan_d(x),scan_d(y)
#define S_3(x,y,z) scan_d(x),scan_d(y),scan_d(z)
#define PI acos(-1)
#define endl '\n'
#define srand() srand(time(0));
#define me(x,y) memset(x,y,sizeof(x));
#define foreach(it,a) for(__typeof((a).begin()) it=(a).begin();it!=(a).end();it++)
#define close() ios::sync_with_stdio(0); cin.tie(0);
#define FOR(x,n,i) for(int i=x;i<=n;i++)
#define FOr(x,n,i) for(int i=x;i<n;i++)
#define fOR(n,x,i) for(int i=n;i>=x;i--)
#define fOr(n,x,i) for(int i=n;i>x;i--)
#define W while
#define sgn(x) ((x) < 0 ? -1 : (x) > 0)
#define bug printf("***********\n");
#define db double
#define ll long long
#define mp make_pair
#define pb push_back
#define sz size
#define fi first
#define se second
#define pf printf
typedef long long LL;
typedef pair <int, int> ii;
const int INF=0x3f3f3f3f;
const LL LINF=0x3f3f3f3f3f3f3f3fLL;
const int dx[]={-1,0,1,0,1,-1,-1,1};
const int dy[]={0,1,0,-1,-1,1,-1,1};
const int maxn=1e2+7;
const int _=1e5+10;
const double EPS=1e-8;
const double eps=1e-8;
const LL mod=1e9+7;
template<class T>inline T min(T a,T b,T c) { return min(min(a,b),c);}
template<class T>inline T max(T a,T b,T c) { return max(max(a,b),c);}
template<class T>inline T min(T a,T b,T c,T d) { return min(min(a,b),min(c,d));}
template<class T>inline T max(T a,T b,T c,T d) { return max(max(a,b),max(c,d));}
template <class T>
inline bool scan_d(T &ret){char c;int sgn;if (c = getchar(), c == EOF){return 0;}
while (c != '-' && (c < '0' || c > '9')){c = getchar();}sgn = (c == '-') ? -1 : 1;ret = (c == '-') ? 0 : (c - '0');
while (c = getchar(), c >= '0' && c <= '9'){ret = ret * 10 + (c - '0');}ret *= sgn;return 1;}

inline bool scan_lf(double &num){char in;double Dec=0.1;bool IsN=false,IsD=false;in=getchar();if(in==EOF) return false;
while(in!='-'&&in!='.'&&(in<'0'||in>'9'))in=getchar();if(in=='-'){IsN=true;num=0;}else if(in=='.'){IsD=true;num=0;}
else num=in-'0';if(!IsD){while(in=getchar(),in>='0'&&in<='9'){num*=10;num+=in-'0';}}
if(in!='.'){if(IsN) num=-num;return true;}else{while(in=getchar(),in>='0'&&in<='9'){num+=Dec*(in-'0');Dec*=0.1;}}
if(IsN) num=-num;return true;}

void Out(LL a){if(a < 0) { putchar('-'); a = -a; }if(a >= 10) Out(a / 10);putchar(a % 10 + '0');}
void print(LL a){ Out(a),puts("");}
//cerr << "run time is " << clock() << endl;

int n,m;
int w[_],b[_];

struct node{
    int to,next;
}G[_<<1];
int head[_],tot;
int rt[_],ls[_*20],rs[_*20],sum[_*20],chairtree,siz;

void build(int &rt,int l,int r){
    rt=++chairtree;
    sum[rt]=0;
    if(l>=r)return ;
    int m =((r-l)>>1)+l;
    build(ls[rt],l,m);
    build(rs[rt],m+1,r);
}

void update(int& rt,int l,int r,int last,int pos){
    rt=++chairtree;
    ls[rt]=ls[last];
    rs[rt]=rs[last];
    sum[rt]=sum[last]+1;

    if(l>=r) return ;
    int m=((r-l)>>1)+l;
    if(pos<=m) update(ls[rt],l  ,m,ls[last],pos);
    else       update(rs[rt],m+1,r,rs[last],pos);
}

int query(int rt,int l,int r,int last,int lca,int flca,int k){
    if(l>=r) return l;
    int m=((r-l)>>1)+l;
    int cnt=sum[ls[rt]]+sum[ls[last]]-sum[ls[lca]]-sum[ls[flca]];
    if(k<=cnt) query(ls[rt],l  ,m,ls[last],ls[lca],ls[flca],k);
    else       query(rs[rt],m+1,r,rs[last],rs[lca],rs[flca],k-cnt);
}

void dfs(int rt,int l,int r){

    int m = ((r-l)>>1)+l;
    printf("%d",sum[rt]);
    if(l>=r) return ;printf("( ");
    dfs(ls[rt],l,m);printf("_%*d,",2,ls[rt]);
    dfs(rs[rt],m+1,r);printf("_%*d )",2,rs[rt]);
}
/**
ChairTree end
*/

void add(int u,int v){
    G[++tot].to=v,G[tot].next=head[u],head[u]=tot;
    G[++tot].to=u,G[tot].next=head[v],head[v]=tot;
}

int dep[_],fa[_],sz[_],son[_];
void dfs1(int u,int f,int d){
    dep[u]=d,fa[u]=f,sz[u]=1,son[u]=0;
    for(int i=head[u],to;i;i=G[i].next){
        to=G[i].to;
        if(to==f)continue;
        dfs1(to,u,d+1);
        sz[u]+=sz[to];
        if(sz[son[u]]<sz[to])son[u]=to;
    }
}

int tree[_],top[_],pre[_],cnt;
void dfs2(int u,int tp){
    top[u]=tp,tree[u]=++cnt,pre[tree[u]]=u;
    update(rt[u],1,siz,rt[fa[u]],w[u]);
    if(!son[u])return;
    dfs2(son[u],tp);
    for(int i=head[u],to;i;i=G[i].next){
        to=G[i].to;
        if(to==fa[u]||to==son[u])continue;
        dfs2(to,to);
    }
}

int Lca(int x,int y){
    int fx=top[x],fy=top[y];
    while(fx!=fy){
        if(dep[fx]<dep[fy])swap(x,y),swap(fx,fy);
        x=fa[fx],fx=top[x];
    }
    if(dep[x]>dep[y])swap(x,y);
    return x;
}

 
void solve() {
	s_2(n,m);
	FOR(1,n,i) s_1(w[i]),b[i]=w[i];
	FOr(1,n,i) {
		int u,v;
		s_2(u,v);
		add(u,v);
	}
	fa[1]=0;
	sort(b+1,b+n+1);
	siz=unique(b+1,b+n+1)-(b+1);
	FOR(1,n,i)
		w[i]=lower_bound(b+1,b+siz+1,w[i])-b;
	build(rt[0],1,siz);
	dfs1(1,0,1);
	dfs2(1,1);
	while(m--) {
		int u,v,k;
		s_3(u,v,k);
		int lca=Lca(u,v);
		//cout<<lca<<endl; 
		print(b[query(rt[u],1,siz,rt[v],rt[lca]
			,rt[fa[lca]],k)]);
	}
}
int main() {
	//freopen( "1.in" , "r" , stdin );
    //freopen( "1.out" , "w" , stdout );
    int t=1;
    //init();
    //s_1(t);
    for(int cas=1;cas<=t;cas++) {
        //printf("Case #%d: ",cas);
        solve();
    }
}

 

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=326573969&siteId=291194637