Count on a tree
题意:
给定一棵树,树上每个节点都有一个权值,问两点之间路径上第K大值
题解:
树上的第k大值,跟区间第k大有些不同,区间第k大每个值在前一个值的基础上新建一棵树,而树上第k大则是在父亲节点的基础上新建一棵树。查询的时候,答案就是root[v] + root[u] - root[lca(v, u)] - root[fa[lca(v,u)]]上的第k大(自己在纸上画一画就知道了)
关于LCA点这里
#include
#include
#include
#include
#include
using namespace std;
const int MAXN=100010;
struct Node
{
int to,next;
};
Node edge[MAXN*2];
int head[MAXN],cnt;
int arr[MAXN],num[MAXN],tot,n,m;
void addEdge(int u,int v)
{
edge[cnt].to=v;
edge[cnt].next=head[u];
head[u]=cnt++;
}
int root[MAXN],sum[MAXN*40],lson[MAXN*40],rson[MAXN*40],cloc;
void build(int l,int r,int &rt)
{
rt=++cloc;
sum[rt]=0;
if(l==r) return;
int mid=(l+r)>>1;
build(l,mid,lson[rt]);
build(mid+1,r,rson[rt]);
}
void update(int last,int &rt,int l,int r,int pos)
{
rt=++cloc;
sum[rt]=sum[last]+1;lson[rt]=lson[last];rson[rt]=rson[last];
if(l==r) return;
int mid=(l+r)>>1;
if(mid>=pos) update(lson[last],lson[rt],l,mid,pos);
else update(rson[last],rson[rt],mid+1,r,pos);
}
int query(int rtu,int rtv,int lca,int falca,int l,int r,int k)
{
if(l==r) return l;
int tmp=sum[lson[rtu]]+sum[lson[rtv]]-sum[lson[lca]]-sum[lson[falca]];
int mid=(l+r)>>1;
if(tmp>=k) return query(lson[rtu],lson[rtv],lson[lca],lson[falca],l,mid,k);
else return query(rson[rtu],rson[rtv],rson[lca],rson[falca],mid+1,r,k-tmp);
}
int sequ[MAXN*2],first[MAXN],vis[MAXN],deep[MAXN*2];
int dp[MAXN*2][20],fat[MAXN],clocks;
void DFS(int u,int fa,int dep)
{
vis[u]=1;
sequ[++clocks]=u;first[u]=clocks;deep[clocks]=dep;fat[u]=fa;
update(root[fa],root[u],1,tot,arr[u]);//在父节点上建树
for(int i=head[u];i!=-1;i=edge[i].next)
{
int v=edge[i].to;
if(vis[v]==0)
{
DFS(v,u,dep+1);
sequ[++clocks]=u;
deep[clocks]=dep;
}
}
}
void ST(int len)
{
for(int i=1;i<=len;i++)
{
dp[i][0]=i;
}
for(int j=1;(1<y) swap(x,y);
return sequ[RMQ(x,y)];
}
int main()
{
int u,v,rak;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%d",arr+i);
num[i]=arr[i];
}
sort(num+1,num+1+n);
tot=unique(num+1,num+1+n)-(num+1);
for(int i=1;i<=n;i++) arr[i]=lower_bound(num+1,num+1+tot,arr[i])-num;
memset(head,-1,sizeof(head));
cnt=clocks=cloc=0;
for(int i=1;i