Count on a tree

题目大意:树上第k小的数。

思路:和区间第k小的数的做法差不多,不过要求一下lca,比较麻烦。

  1 #include<bits/stdc++.h>
  2 #define fi first
  3 #define se second
  4 #define pb push_back
  5 #define mk make_pair
  6 #define pii pair<int,int>
  7 #define read(x) scanf("%d",&x)
  8 #define lread(x) scanf("%lld",&x)
  9 using namespace std;
 10 
 11 typedef long long ll;
 12 const int N=1e5+7;
 13 const int M=1e5+1;
 14 const int inf=0x3f3f3f3f;
 15 const ll INF=0x3f3f3f3f3f3f3f3f;
 16 
 17 int n,m,top,root[N],fa[N],a[N],hs[N],vs[N<<1],dp[N<<1][25],tot,f[N],d[N];
 18 vector<int> e[N];
 19 struct seg_tree
 20 {
 21     int cnt=0;
 22     struct node
 23     {
 24         int l,r,sum;
 25     }a[N*20];
 26     void updata(int l,int r,int &x,int y,int v)
 27     {
 28         a[++cnt]=a[y]; x=cnt; a[x].sum++;
 29         if(l==r)
 30             return;
 31         int mid=(l+r)>>1;
 32         if(v<=hs[mid])
 33             updata(l,mid,a[x].l,a[y].l,v);
 34         else
 35             updata(mid+1,r,a[x].r,a[y].r,v);
 36     }
 37     int query(int l,int r,int x,int y,int z,int t,int k)
 38     {
 39         if(l==r)
 40             return hs[l];
 41         int mid=(l+r)>>1;
 42         int ans=a[a[x].l].sum+a[a[y].l].sum-a[a[z].l].sum-a[a[t].l].sum;
 43         if(ans>=k)
 44             return query(l,mid,a[x].l,a[y].l,a[z].l,a[t].l,k);
 45         else
 46             return query(mid+1,r,a[x].r,a[y].r,a[z].r,a[t].r,k-ans);
 47 
 48     }
 49 }seg;
 50 void dfs(int u,int p)
 51 {
 52     fa[u]=p;
 53     seg.updata(1,top,root[u],root[p],a[u]);
 54     for(int v:e[u])
 55         if(v!=p) dfs(v,u);
 56 }
 57 void dfs(int u,int p,int s)
 58 {
 59     vs[++tot]=u;
 60     d[u]=s;
 61     f[u]=tot;
 62     for(int i=0;i<e[u].size();i++)
 63     {
 64         int to=e[u][i];
 65         if(to==p) continue;
 66         dfs(to,u,s+1);
 67         vs[++tot]=u;
 68     }
 69 }
 70 void work_rmq()
 71 {
 72     for(int i=1;i<=tot;i++) dp[i][0]=vs[i];
 73     int up=log(tot)/log(2);
 74     for(int j=1;j<=up;j++)
 75     {
 76         int t=(1<<j)-1;
 77         for(int i=1;i+t<=tot;i++)
 78         {
 79             int a=dp[i][j-1],b=dp[i+(1<<(j-1))][j-1];
 80             if(d[a]<=d[b]) dp[i][j]=a;
 81             else dp[i][j]=b;
 82         }
 83     }
 84 }
 85 int get_lca(int u,int v)
 86 {
 87     int l,r;
 88     if(f[u]<f[v]) l=f[u],r=f[v];
 89     else l=f[v],r=f[u];
 90     int j=log(r-l+1)/log(2);
 91     int a=dp[l][j],b=dp[r-(1<<j)+1][j];
 92     if(d[a]<d[b]) return a;
 93     else return b;
 94 }
 95 int main()
 96 {
 97     read(n); read(m);
 98     for(int i=1;i<=n;i++)
 99         read(a[i]),fa[i]=i,hs[++top]=a[i];
100     for(int i=1;i<n;i++)
101     {
102         int f,t;
103         read(f); read(t);
104         e[f].push_back(t);
105         e[t].push_back(f);
106     }
107     sort(hs+1,hs+top+1);
108     top=unique(hs+1,hs+top+1)-hs-1;
109     dfs(1,0);
110     dfs(1,0,0);
111     work_rmq();
112     for(int i=1;i<=m;i++)
113     {
114         int u,v,k;
115         read(u); read(v); read(k);
116         int lca=get_lca(u,v);
117         int x=root[u],y=root[v];
118         int z=root[lca];
119         int t=fa[lca]==lca ? 0:root[fa[lca]];
120         int ans=seg.query(1,top,x,y,z,t,k);
121         printf("%d\n",ans);
122     }
123     return 0;
124 }
125 /*
126 */

 

转载于:https://www.cnblogs.com/CJLHY/p/8465829.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
# COT - Count on a tree ## 题面翻译 # 本题必须使用 C++98 提交 给你一棵有n个结点的树,节点编号为1~n。 每个节点都有一个权值。 要求执行以下操作: U V K:求从节点u到节点v的第k小权值。 # 输入输出格式 ## 输入格式 第一行有两个整数n和m(n,m≤100000) 第二行有n个整数。 第i个整数表示第i个节点的权值。 接下来的n-1行中,每行包含两个整数u v,表示u和v之间有一条边。 接下来的m行,每行包含三个整数U V K,进行一次操作。 ## 输出格式 对于每个操作,输出结果。 ## 题目描述 You are given a tree with **N** nodes. The tree nodes are numbered from **1** to **N**. Each node has an integer weight. We will ask you to perform the following operation: - **u v k** : ask for the kth minimum weight on the path from node **u** to node **v** ## 输入格式 In the first line there are two integers **N** and **M**. (**N, M** <= 100000) In the second line there are **N** integers. The ith integer denotes the weight of the ith node. In the next **N-1** lines, each line contains two integers **u** **v**, which describes an edge (**u**, **v**). In the next **M** lines, each line contains three integers **u** **v** **k**, which means an operation asking for the kth minimum weight on the path from node **u** to node **v**. ## 输出格式 For each operation, print its result. ## 样例 #1 ### 样例输入 #1 ``` 8 5 105 2 9 3 8 5 7 7 1 2 1 3 1 4 3 5 3 6 3 7 4 8 2 5 1 2 5 2 2 5 3 2 5 4 7 8 2 ``` ### 样例输出 #1 ``` 2 8 9 105 7 ```
最新发布
07-20
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值