题面:P3899 [湖南集训]谈笑风生

题解:

我很喜欢这道题。

因为A是给定的,所以实质是求二元组的个数。我们以A(即给定的P)作为基点寻找答案,那么情况分两类。一种是B为A的父亲,另一种是A为B的父亲。

第一种情况很好处理,写法见代码,懒得讲,反正很简单的。

第二种情况的话,按Dfs序建主席树,用主席树维护下标为Dep的序列,每次用Size-1(因为不能取本身;Size[i]即为以i为根的子树节点数)去更新,

询问的时候在以A为根的子树中查找Dep[A]+1~Dep[A]+K的和即可。

不思考自然是看不懂的。

代码:

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 #define ll long long
 5 #define max(a,b) ((a)>(b)?(a):(b))
 6 using namespace std;
 7 inline ll rd(){
 8     ll x=0,f=1;char c=getchar();
 9     while(c<'0'||c>'9'){if(c=='-')f=-1; c=getchar();}
10     while(c>='0'&&c<='9'){x=x*10+c-'0'; c=getchar();}
11     return f*x;
12 }
13 const int maxn=(3e5)+50,maxq=(3e5)+50;
14 int N,Q,num_edge=0,edge_head[maxn],U,V,Le[maxn],Ri[maxn],P,root[maxn],num_treenode=0,maxdep;
15 int Dfn[maxn],num_dfn=0;
16 struct Edge{int to,nx;}edge[maxn<<1];
17 ll Dep[maxn],Size[maxn],K,w,ans;
18 inline void Add_edge(int from,int to){
19     edge[++num_edge].nx=edge_head[from];
20     edge[num_edge].to=to;
21     edge_head[from]=num_edge;
22     return;
23 }
24 struct Tree{int l,r,ls,rs;ll sum;}t[(maxn<<3)+(maxn*20)];
25 inline void Build(int x,int l,int r){//建以深度为下标的主席树
26     t[x].l=l;t[x].r=r;int mid=(l+r)>>1;
27     if(l==r)return;
28     Build(t[x].ls=++num_treenode,l,mid);
29     Build(t[x].rs=++num_treenode,mid+1,r);
30     return;
31 }
32 inline void Dfs(int x,int fa){
33     Dfn[++num_dfn]=x;
34     Le[x]=num_dfn;
35     Dep[x]=Dep[fa]+1;
36     maxdep=max(maxdep,Dep[x]);
37     Size[x]=1;
38     for(int i=edge_head[x];i;i=edge[i].nx){
39         int y=edge[i].to;
40         if(y!=fa){
41             Dfs(y,x);
42             Size[x]+=Size[y];
43         }
44     }
45     Ri[x]=num_dfn;
46     return;
47 }
48 inline void Update(int u,int x,int q,int s){
49     int l=t[u].l,r=t[u].r,mid=(l+r)>>1;
50     t[x].l=l;t[x].r=r;
51     if(l==r&&l==q){t[x].sum=t[u].sum+s; return;}
52     if(q<=mid){
53         t[x].rs=t[u].rs;
54         Update(t[u].ls,t[x].ls=++num_treenode,q,s);
55     }
56     else{
57         t[x].ls=t[u].ls;
58         Update(t[u].rs,t[x].rs=++num_treenode,q,s);
59     }
60     t[x].sum=t[t[x].ls].sum+t[t[x].rs].sum;
61     return;
62 }
63 inline void Query(int u,int x,int ql,int qr){
64     int l=t[u].l,r=t[u].r,mid=(l+r)>>1;
65     if(ql<=l&&r<=qr){
66         ans=ans+t[x].sum-t[u].sum;
67         return;
68     }
69     if(ql<=mid)Query(t[u].ls,t[x].ls,ql,qr);
70     if(qr>mid) Query(t[u].rs,t[x].rs,ql,qr);
71     return;
72 }
73 int main(){
74     N=rd();Q=rd();
75     for(int i=1;i<N;i++){
76         U=rd();V=rd();
77         Add_edge(U,V);
78         Add_edge(V,U);
79     }
80     Dep[0]=-1;//由于我的写法的原因,把根节点的深度设为0
81     Dfs(1,0);
82     Build(root[0]=++num_treenode,1,maxdep+5);
83     Dfn[0]=0;
84     for(int i=1;i<=num_dfn;i++)
85         Update(root[Dfn[i-1]],root[Dfn[i]]=++num_treenode,Dep[Dfn[i]],Size[Dfn[i]]-1);
86     while(Q--){
87         P=rd();K=rd();
88         ans=0;
89         //先往父亲找
90         if(Dep[P]>=K)w=K;else w=Dep[P];
91         ans+=w*(Size[P]-1);
92         //往儿子找
93         Query(root[P],root[Dfn[Ri[P]]],Dep[P]+1,Dep[P]+K);
94         printf("%lld\n",ans);
95     }
96     return 0;
97 }


By:AlenaNuna

转载于:https://www.cnblogs.com/AlenaNuna/p/10492434.html

主席树 || 可持久化线段树 || BZOJ 3653: 谈笑风生 || Luogu P3899 [湖南集训]谈笑风生...相关推荐

  1. luogu P3899 [湖南集训]谈笑风生 线段树合并

    Description 设T 为一棵有根树,我们做如下的定义: ? 设a和b为T 中的两个不同节点.如果a是b的祖先,那么称"a比b不知道 高明到哪里去了". ? 设a 和 b 为 ...

  2. 洛谷 - P3899 [湖南集训]谈笑风生(dfs序+主席树/二维数点)

    题目链接:点击查看 题目大意:设 TTT 为一棵有根树,我们做如下的定义: 设 aaa 和 bbb 为 TTT 中的两个不同节点.如果 aaa 是 bbb 的祖先,那么称"aaa 比 bbb ...

  3. P3899 [湖南集训]谈笑风生(线段树合并)

    P3899 [湖南集训]谈笑风生 给定一颗以111号节点为根的树,如果a≠ba \neq ba​=b,且aaa是bbb的祖先,则aaa比bbb更厉害,如果a≠ba \neq ba​=b,且dis( ...

  4. 主席树 - 可持久化线段树

    模板 P3834 [模板]可持久化线段树 2(主席树) 区间求第 \(k\) 大 模板代码 #include<bits/stdc++.h> using namespace std; #de ...

  5. BZOJ 3483 SGU505 Prefixes and suffixes(字典树+可持久化线段树)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=3483 [题目大意] 给出一些串,同时给出m对前缀后缀,询问有多少串满足给出的前缀后缀模 ...

  6. Codeforces1422 F.Boring Queries(根号分治+线段树+可持久化线段树)

    题意: 解法: 如果问题可以离线,那么莫队可以直接冲过去,可惜离不得. 每个数最多只有一个>sqrt的质因子,sqrt(2e5)<90, 开90棵线段树分别维护前90个质因子的区间最大指数 ...

  7. P3899 [湖南集训]谈笑风生 主席树解决二维数点

    传送门 文章目录 题意: 思路: 题意: 思路: 由于a,ba,ba,b都比ccc厉害,那么a,ba,ba,b一定是某个是某个的祖先.那么就分为两种情况了: (1)(1)(1) bbb在aaa上面,约 ...

  8. 主席树 || 可持久化线段树 || LCA || BZOJ 2588: Spoj 10628. Count on a tree || Luogu P2633 Count on a tree...

    题面: Count on a tree 题解: 主席树维护每个节点到根节点的权值出现次数,大体和主席树典型做法差不多,对于询问(X,Y),答案要计算ans(X)+ans(Y)-ans(LCA(X,Y) ...

  9. 解题报告:P3834 【模板】可持久化线段树 2(主席树)详解

    P3834 [模板]可持久化线段树 2(主席树) 题解 P3834 [[模板]可持久化线段树 2(主席树)] 1)静态求第k大数 可持久化线段树,不能用堆的方法存子结点了,所以用指针l表示左儿子r表示 ...

  10. 可持久化线段树——主席树

    前言: 最近心(po)血(yu)来(ya)潮(li)学习了一下主席树.(再不学就落伍了) 主席树,即可持久化线段树,支持维护和查询区间的第\(k\)大(小).区间不同种类个数等,基于线段树的思想之上 ...

最新文章

  1. 报告:美国AI投资占全球56% 中国第二增长最快
  2. 零基础学习大数据开发需要多久能工作?
  3. 当我真正开始爱自己——查理·卓别林
  4. Centos配置在线yum源
  5. android webdav客户端,WebDAV精灵(WebDAV客户端)
  6. 一种虚拟现实技术用计算机,虚拟现实技术有哪几大分类?
  7. nrf51822微信开发入门学习笔记1:开始前的准备
  8. MySQL Left Join,Right Join
  9. C语言中报段错误(核心已转储)的常见问题
  10. 【虚拟光驱怎么安装Win7系统】
  11. 微信小程序转码机器人
  12. 使用TypeScript两年后,还值得吗?
  13. HZNU 与班尼特·胡迪一起攻破浮空城 【DP】
  14. 云算法——骑士在棋盘上的概率之公主当不了堂吉诃德
  15. linux系统进去是guest用户t,ubuntu普通用户变为root用户后,只能guest身份进系统(linux的权限问题)...
  16. python房价预测_python房价预测
  17. 【观察】PowerScale:构筑“智慧广电”创新基石
  18. dlink平台上面flink-connect-kudu开发
  19. MP4/MP3解封装ffmpeg(十三)
  20. 营销策略解析:papi酱、李子柒等网红的背后究竟隐藏着什么?

热门文章

  1. NP、OSPF虚链路
  2. TCP为什么避免测量重传报文段SampleRTT;TCP为什么等到三个重复的ack后才快速重传
  3. 初始化Metasploit-Framework
  4. 新人如何使用git加入到团队开发中
  5. QTP不识别树结构中的点击事件
  6. Redis脚本实现分布式锁
  7. 五、OpenStack安装Nova
  8. 文件上传下载——sz和rz
  9. Java thread 怎么用_Java Thread 的使用
  10. 21个非常实用的She脚本实例