您的位置:首页 > 其它

SPOJ 10628 Count on The tree .. .. 主席树

2014-07-30 14:17 465 查看
先离散化出 cnt个不同的数,再以这cnt个不同的数来建立主席树,主席树记录的是某节点的数量,

这样就可以通过树的加减操作,来判断< a[num] 的数有多少个了。。

这题只用从根序列开始,记录到每个点的线段树

DFS从根开始构造序列

可以知道  dist[a,b]  = dist[a,root] + dist[b,root] - dist[ lca,root] - dist[fa[lca] , root];

这就是Query的内容了。

ORZ

//tpl
//ipqhjjybj_tpl.h
//header.h
#include <cstdio>
#include <cstdlib>
#include <map>
#include <set>
#include <algorithm>
#include <cstring>
#include <iostream>
#include <vector>
#include <string>
#include <queue>

#define mp(x,y) make_pair(x,y)
#define pii pair<int,int>
#define pLL pair<long long ,long long>
#define rep(i,j,k) for(int i = j; i < k;i++)
#define nrep(i,j,k) for(int i = j; i <= k;i++)

using namespace std;

const int N = 111111;
const int INF = 0x3f3f3f3f;
const int maxs = 20;
int a
,b
,fa
,root
,ls[N*20],rs[N*20],deep
;
int sum[N*20];
int flca
[20];
vector<int> g
;
int tot;

void build(int l,int r,int &rt){
rt = tot++;
sum[rt] = 0;
if(l>=r)return;
int mid = (l+r)>>1;
build(l,mid,ls[rt]);
build(mid+1,r,rs[rt]);
}
void update(int last,int p,int l,int r,int &rt){
rt = tot++;
ls[rt] = ls[last], rs[rt] = rs[last];
sum[rt] = sum[last]+1;
if(l>=r) return;
int mid = (l+r)>>1;
if(p <= mid){
update(ls[last],p,l,mid,ls[rt]);
}else{
update(rs[last],p,mid+1,r,rs[rt]);
}
}
int query(int left_rt,int right_rt,int lca,int flc,int l,int r,int k){
if(l>=r) return l;
int mid = (l+r)>>1;
int cnt = sum[ls[left_rt]] + sum[ls[right_rt]] - sum[ls[lca]] - sum[ls[flc]];
if(k <= cnt)
return query(ls[left_rt],ls[right_rt],ls[lca],ls[flc],l,mid,k);
else return query(rs[left_rt],rs[right_rt],rs[lca],rs[flc],mid+1,r,k-cnt);
}
int getlca(int u,int v){
if(deep[u] > deep[v]) swap(u,v);
if(deep[u] < deep[v]){
int del = deep[v] - deep[u];
for(int i = 0;i < maxs;i++)
if(del & (1<<i)) v = flca[v][i];
}
if(u!=v){
for(int i = maxs-1; i >= 0;i--)
if(flca[u][i] != flca[v][i])
u = flca[u][i], v = flca[v][i];
u = flca[u][0];
}
return u;
}
void dfs(int u,int f,int n){
flca[u][0] = fa[u] = f , deep[u] = deep[f] + 1;
for(int i = 1;i < maxs;i++) {
flca[u][i] = flca[flca[u][i-1]][i-1];
//printf("flca[%d][%d]=%d\n",u,i,flca[u][i]);
}
update(root[f],a[u],1,n,root[u]);
for(int i = 0;i < g[u].size();i++){
int v = g[u][i];
if(v != f)
dfs(v,u,n);
}
}
int main(){
int n,m;
int u,v,w;
while(scanf("%d %d",&n,&m)!=EOF){
nrep(i,1,n) g[i].clear();
nrep(i,1,n) scanf("%d",a+i);
memcpy(b,a,sizeof(a));
sort(b+1,b+1+n);
int cnt = unique(b+1,b+1+n) - b-1;
nrep(i,1,n){
a[i] = lower_bound(b+1,b+cnt+1,a[i])-b;
//printf("a[%d]=%d\n",i,a[i]);
}
rep(i,1,n){
scanf("%d %d",&u,&v);
g[u].push_back(v) , g[v].push_back(u);
}
tot = 0;
build(1,cnt,root[0]);
deep[0] = 0;
dfs(1,0,cnt);
nrep(zz,1,m){
scanf("%d %d %d",&u,&v,&w);
int lca = getlca(u,v);
int ans = query(root[u],root[v],root[lca],root[fa[lca]],1,cnt,w);

printf("%d\n",b[ans]);
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  ACM SPOJ 主席树