P3899 [湖南集训]谈笑风生

题目描述

Solution

我们考虑离线询问,将询问放在相对应的子树ppp中计算答案。

显然a,b,ca,b,ca,b,c的位置关系有两种情况:

  1. bbb是aaa的祖先,ccc是aaa的子孙。
  2. aaa是bbb的祖先,ccc是bbb的子孙。

第一种位置关系很容易统计答案。
方案数为min(dep[a]−1,k)∗(size[a]−1)min(dep[a]-1,k)*(size[a]-1)min(dep[a]−1,k)∗(size[a]−1)。

第二种位置关系可以DSUontreeDSU\;on\;\;treeDSUontree或长链剖分计算。
显然DSUontreeDSU\;on\;\;treeDSUontree简单啊QAQQAQQAQ。

对于每一个bbb,合法的ccc为bbb的子孙节点,因此相当于每一个bbb的贡献为size[b]−1size[b]-1size[b]−1。我们在DSUontreeDSU\;on\;\;treeDSUontree的过程中记录一个值f[x]f[x]f[x]表示当前子树中深度为xxx的所有bbb的贡献和,那么总答案就是每一个子树aaa的∑i=1kf[dep[a]+i]\sum_{i=1}^{k}{f[dep[a]+i]}∑i=1k​f[dep[a]+i]。

相当于我们要支持单点修改,区间求和,用树状数组维护f[x]f[x]f[x]即可。

时间复杂度O(nlg2n)O(nlg^2n)O(nlg2n),但实测挺快的。

#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <queue>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cctype>
#include <string>
#include <cstring>
#include <ctime>
#include <cassert>
#include <string.h>
//#include <unordered_set>
//#include <unordered_map>
//#include <bits/stdc++.h>#define MP(A,B) make_pair(A,B)
#define PB(A) push_back(A)
#define SIZE(A) ((int)A.size())
#define LEN(A) ((int)A.length())
#define FOR(i,a,b) for(int i=(a);i<(b);++i)
#define fi first
#define se secondusing namespace std;template<typename T>inline bool upmin(T &x,T y) { return y<x?x=y,1:0; }
template<typename T>inline bool upmax(T &x,T y) { return x<y?x=y,1:0; }typedef long long ll;
typedef unsigned long long ull;
typedef long double lod;
typedef pair<int,int> PR;
typedef vector<int> VI;const lod eps=1e-11;
const lod pi=acos(-1);
const int oo=1<<30;
const ll loo=1ll<<62;
const int mods=998244353;
const int MAXN=600005;
const int INF=0x3f3f3f3f;//1061109567
/*--------------------------------------------------------------------*/
inline int read()
{int f=1,x=0; char c=getchar();while (c<'0'||c>'9') { if (c=='-') f=-1; c=getchar(); }while (c>='0'&&c<='9') { x=(x<<3)+(x<<1)+(c^48); c=getchar(); }return x*f;
}
vector<int> e[MAXN];
vector<PR> Q[MAXN];
int sz[MAXN],mx[MAXN],dep[MAXN],n,q;
ll sum[MAXN],Ans[MAXN];
int lowbit(int x){ return x&(-x); }
void change(int x,ll y){ for (;x<=n;x+=lowbit(x)) sum[x]+=y; }
ll query(int x){ ll ans=0; for (;x;x-=lowbit(x)) ans+=sum[x]; return ans; }
void dfs1(int x,int father)
{sz[x]=1,mx[x]=0,dep[x]=dep[father]+1;for (auto v:e[x]){if (v==father) continue;dfs1(v,x);sz[x]+=sz[v];if (sz[mx[x]]<sz[v]) mx[x]=v;}
}
void modify(int x,int c,int father,int mx)
{//  cout<<x<<" "<<dep[x]<<":"<<c*(sz[x]-1)<<endl;change(dep[x],c*(sz[x]-1));for (auto v:e[x]){if (v==father||v==mx) continue;modify(v,c,x,mx);}
}
void dfs2(int x,int father,int flag)
{for (auto v:e[x]){if (v==father||v==mx[x]) continue;dfs2(v,x,0);}if (mx[x]) dfs2(mx[x],x,1);modify(x,1,father,mx[x]);for (auto y:Q[x]) {Ans[y.fi]=query(min(n,dep[x]+y.se))-query(dep[x])+1ll*(min(y.se,dep[x]-1))*(sz[x]-1);
//      cout<<y.fi<<" "<<x<<" "<<y.se<<" "<<query(min(n,dep[x]+y.se))<<" "<<query(dep[x])<<endl;}if (!flag) modify(x,-1,father,0);
}
int main()
{n=read(),q=read();for (int i=1;i<n;i++){int u=read(),v=read();e[u].PB(v);e[v].PB(u);}for (int i=1;i<=q;i++) {int x=read(),y=read();Q[x].PB(MP(i,y));}dfs1(1,0);dfs2(1,0,1);for (int i=1;i<=q;i++) printf("%lld\n",Ans[i]);return 0;
}

P3899 [湖南集训]谈笑风生相关推荐

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

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

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

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

  3. 洛谷P3899 [湖南集训]谈笑风生

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

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

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

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

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

  6. P3899 [湖南集训]更为厉害(线段树合并、长链剖分、二维数点)

    P3899 [湖南集训]更为厉害 若 deepb<deepa\text{deep}_b<\text{deep}_adeepb​<deepa​:c 在点 a 的子树中,根据乘法原理计算 ...

  7. [湖南集训] 谈笑风生

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

  8. [湖南集训]谈笑风生

    谈笑风生 题目大意: 给定a,求任何一个距 a 距离不超过给定的 k 的 b ,然后求一个 c 使得其为 a,b 的后代,求这样的三元组共有多少个. 数据结构好题啊! 解法分析: 我们可以深搜两遍(其 ...

  9. bzoj 3653 [湖南集训]谈笑风生

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

最新文章

  1. UIButton长按事件
  2. Android 实现简单的插件化模块化
  3. pycharms怎么看文件被什么引用_办公室文件柜怎么选,选购文件柜有什么窍门
  4. FPGA加速BCNN,模型20倍剪枝率、边缘设备超5000帧/秒推理吞吐量
  5. SVN 常用命令笔记
  6. 在WebLogic 12c上运行RichFaces
  7. 什么是CSS?你真的理解?
  8. linux安装lrzsz,并使用rz sz 命令
  9. PyTorch 1.0 中文文档:Windows FAQ
  10. Redmi 10X Pro 5G曝光:四种配色、两种存储版本可选
  11. Android O HIDL的使用例子 -- 蓝牙HCI 服务进程
  12. xshell使用隧道
  13. 投标文件模板 | 信息化智慧校园项目投标方案 | word版
  14. 思科交换机链路聚合详解收集
  15. 电脑中的驱动程序是什么,是干什么的
  16. 华为手机图标怎么变小_华为手机字太小看不清?那是你不会设置!四种方法让手机显示变大...
  17. 程序员面试揭秘之程序员靠什么途径去美国工作?
  18. 优质百度网盘资源分享(计算机篇)
  19. wiki语料库训练检索式聊天机器人
  20. 员工不服管,怎么办?

热门文章

  1. 看似毫无规律的各种现象
  2. 女孩看男孩VS男孩看女孩
  3. 公厕的门下面为什么都要空一截?难道是为了和别人分享我中午吃的两碗螺狮粉?
  4. 学习总结之数据挖掘三大类六分项
  5. python win7 sp1_[ Python - 15 ] win7安装paramiko问题总汇
  6. java字符串拼接例子_Java详解【String】+【StringBuilder vs StringBuffer】+【字符串拼接】...
  7. 用gis打开tif格式_如何下载SHP矢量格式的等高线
  8. android6.0重力工具箱,重力工具箱 GravityBox For Android8.0/8.1(Oreo)稳定版发布!
  9. iphone4 base64 mp3 无法解析 html5,javascript - 如何使用HTML5在firefox上播放base64音频数据? - 堆栈内存溢出...
  10. 360浏览器5兼容模式吗_个独模式真能将企业总体税负降低至5%吗,为何大家都热衷核定征收...