题意:一棵树q次查询,每次查询给三个不同的点,要求计算到这三个点的比其他两个距离都要小的点数

题解:很明显的lca,倍增的找中点,关键是两个点的中点很好找,但是三个点不好找,我刚开始还准备分类讨论,后来发现巨麻烦,其实可以用线段树来维护算a的答案其实就是a在b下的答案和a在c下的答案的交集,可以用线段树区间求和区间查询做,每次更新完之后复原就不用memset线段树了

//#pragma comment(linker, "/stack:200000000")
//#pragma GCC optimize("Ofast,no-stack-protector")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
//#pragma GCC optimize("unroll-loops")
#include<bits/stdc++.h>
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define pi acos(-1.0)
#define ll long long
#define vi vector<int>
#define mod 1000000007
#define C 0.5772156649
#define ls l,m,rt<<1
#define rs m+1,r,rt<<1|1
#define pil pair<int,ll>
#define pli pair<ll,int>
#define pii pair<int,int>
#define cd complex<double>
#define ull unsigned long long
#define base 1000000000000000000
#define fio ios::sync_with_stdio(false);cin.tie(0) using namespace std; const double g=10.0,eps=1e-;
const int N=+,maxn=+,inf=0x3f3f3f3f,INF=0x3f3f3f3f3f3f3f3f; vi v[N];
int dep[N],n,sz[N],fa[][N];
int le[N],ri[N],id[N],cnt;
void dfs(int u,int f)
{
le[u]=++cnt;
id[cnt]=u;
fa[][u]=f;
sz[u]=;
for(int i=;i<v[u].size();i++)
{
int x=v[u][i];
if(x!=f)dep[x]=dep[u]+,dfs(x,u),sz[u]+=sz[x];
}
ri[u]=cnt;
}
int lazy[N<<],val[N<<];
void pushdown(int l,int r,int rt)
{
if(lazy[rt]!=)
{
int m=(l+r)>>;
val[rt<<]+=(m-l+)*lazy[rt];
val[rt<<|]+=(r-m)*lazy[rt];
lazy[rt<<]+=lazy[rt];
lazy[rt<<|]+=lazy[rt];
lazy[rt]=;
}
}
void pushup(int rt)
{
val[rt]=val[rt<<]+val[rt<<|];
}
void build(int l,int r,int rt)
{
lazy[rt]=val[rt]=;
if(l==r)return ;
int m=(l+r)>>;
build(ls);build(rs);
}
void update(int c,int L,int R,int l,int r,int rt)
{
if(L<=l&&r<=R)
{
val[rt]+=(r-l+)*c;
lazy[rt]+=c;
return ;
}
pushdown(l,r,rt);
int m=(l+r)>>;
if(L<=m)update(c,L,R,ls);
if(m<R)update(c,L,R,rs);
pushup(rt);
}
int query(int L,int R,int l,int r,int rt)
{
if(L<=l&&r<=R)return val[rt];
pushdown(l,r,rt);
int m=(l+r)>>,ans=;
if(L<=m)ans+=query(L,R,ls);
if(m<R)ans+=query(L,R,rs);
return ans;
}
void init()
{
dep[]=;
cnt=;
dfs(,-);
build(,cnt,);
for(int i=;i<;i++)
for(int j=;j<=n;j++)
fa[i][j]=fa[i-][fa[i-][j]];
}
int lca(int x,int y)
{
if(dep[x]>dep[y])swap(x,y);
for(int i=;i<;i++)
if((dep[y]-dep[x])>>i&)
y=fa[i][y];
if(x==y)return x;
for(int i=;i>=;i--)
{
if(fa[i][x]!=fa[i][y])
{
x=fa[i][x];
y=fa[i][y];
}
}
return fa[][x];
}
int go(int u,int dis)
{
for(int i=;i>=;i--)
if(dis>=(<<i))
dis-=(<<i),u=fa[i][u];
return u;
}
int solve(int a,int b,int c)
{
int tle,tri,ans=;
if(dep[a]>=dep[b])
{
int dis=dep[a]+dep[b]-*dep[lca(a,b)];
int x=go(a,dis/);
if(dis%==)x=go(a,dis/-);
update(,le[x],ri[x],,cnt,);
tle=le[x],tri=ri[x];
}
else
{
int dis=dep[a]+dep[b]-*dep[lca(a,b)];
int x=go(b,dis/);
update(,,cnt,,cnt,);
update(-,le[x],ri[x],,cnt,);
tle=le[x],tri=ri[x];
}
if(dep[a]>=dep[c])
{
int dis=dep[a]+dep[c]-*dep[lca(a,c)];
int x=go(a,dis/);
if(dis%==)x=go(a,dis/-);
ans=query(le[x],ri[x],,cnt,);
}
else
{
int dis=dep[a]+dep[c]-*dep[lca(a,c)];
int x=go(c,dis/);
ans=query(,cnt,,cnt,);
ans-=query(le[x],ri[x],,cnt,);
}
if(dep[a]>=dep[b])update(-,tle,tri,,cnt,);
else update(-,,cnt,,cnt,),update(,tle,tri,,cnt,);
return ans;
}
int main()
{
int T;scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
for(int i=;i<=n;i++)v[i].clear();
for(int i=;i<n;i++)
{
int a,b;
scanf("%d%d",&a,&b);
v[a].pb(b),v[b].pb(a);
}
init();
int q;scanf("%d",&q);
while(q--)
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
// printf("%d\n",solve(b,a,c));
printf("%d %d %d\n",solve(a,b,c),solve(b,a,c),solve(c,a,b));
}
}
return ;
}
/***********************
1
9
1 2
1 3
1 4
2 5
2 6
2 7
6 8
6 9
2
1 2 8
2 1 4
***********************/

UVALive - 6712 lca+dfs序线段树的更多相关文章

  1. Educational Codeforces Round 6 E dfs序+线段树

    题意:给出一颗有根树的构造和一开始每个点的颜色 有两种操作 1 : 给定点的子树群体涂色 2 : 求给定点的子树中有多少种颜色 比较容易想到dfs序+线段树去做 dfs序是很久以前看的bilibili ...

  2. 【BZOJ-3252】攻略 DFS序 + 线段树 + 贪心

    3252: 攻略 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 339  Solved: 130[Submit][Status][Discuss] D ...

  3. Codeforces 343D Water Tree(DFS序 + 线段树)

    题目大概说给一棵树,进行以下3个操作:把某结点为根的子树中各个结点值设为1.把某结点以及其各个祖先值设为0.询问某结点的值. 对于第一个操作就是经典的DFS序+线段树了.而对于第二个操作,考虑再维护一 ...

  4. BZOJ2434 [Noi2011]阿狸的打字机(AC自动机 + fail树 + DFS序 + 线段树)

    题目这么说的: 阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机.打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P'两个字母.经阿狸研究发现,这个打字机是这样工作的: 输入小 ...

  5. POJ 3321 DFS序+线段树

    单点修改树中某个节点,查询子树的性质.DFS序 子树序列一定在父节点的DFS序列之内,所以可以用线段树维护. 1: /* 2: DFS序 +线段树 3: */ 4:   5: #include < ...

  6. 【XSY2667】摧毁图状树 贪心 堆 DFS序 线段树

    题目大意 给你一棵有根树,有\(n\)个点.还有一个参数\(k\).你每次要删除一条长度为\(k\)(\(k\)个点)的祖先-后代链,问你最少几次删完.现在有\(q\)个询问,每次给你一个\(k\), ...

  7. F - Change FZU - 2277 (DFS序+线段树)

    题目链接: F - Change FZU - 2277 题目大意: 题意: 给定一棵根为1, n个结点的树. 有q个操作,有两种不同的操作 (1) 1 v k x : a[v] += x, a[v ' ...

  8. BZOJ4551[Tjoi2016&Heoi2016]树——dfs序+线段树/树链剖分+线段树

    题目描述 在2016年,佳媛姐姐刚刚学习了树,非常开心.现在他想解决这样一个问题:给定一颗有根树(根为1),有以下 两种操作:1. 标记操作:对某个结点打上标记(在最开始,只有结点1有标记,其他结点均 ...

  9. BZOJ1103 [POI2007]大都市meg dfs序 线段树

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ1103 题意概括 一棵树上,一开始所有的边权值为1,我们要支持两种操作: 1. 修改某一条边的权值为 ...

随机推荐

  1. UVA10905: Children's Game(排序)

    题目:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=68990#problem/A 题目需求:,给n个数字,将它们重新排序得到一个最大的数 ...

  2. Java栈之链式栈存储结构实现

    一.链栈 采用单链表来保存栈中所有元素,这种链式结构的栈称为链栈. 二.栈的链式存储结构实现 package com.ietree.basic.datastructure.stack; /** * 链 ...

  3. Linux系统——NFS网络文件系统

    在企业集群架构的工作场景中,NFS网络文件系统一般被用来存储共享视频,图片,附件等静态资源文件,通常网站用户上传的文件都会放到NFS共享里,然后前端所有的节点访问这些静态资源时都会读取NFS存储上的资 ...

  4. C#:对含有中文的字符串进行MD5加密

    MD5CryptoServiceProvider MD5 = new MD5CryptoServiceProvider(); var Sign = BitConverter.ToString(MD5. ...

  5. android 列表图片优化经历

    先上个优化之后的fps图,丝滑流畅:具体实现请看最终优化后的app 背景:一个通讯录app(开源地址),每次登陆时,针对每个用户,如果头像图片不在本地,则生成一个异步下载任务(AsyncTask). ...

  6. springer论文模板参考文献的顺序问题

    latex环境 MikTex 2.9 + TeXstudio 2.12.8 (+ Mendeley) 问题 springer提供的latex模板 中最后的参考文献是按照字母顺序排列的.我想要弄成按照文 ...

  7. XPath Checker 和 firebug 插件使用

    安装插件: 1.firebug 2.FirePath 3.xpath finder 4.XPath Checker XPath Checker 下载安装 https://addons.mozilla. ...

  8. Spring MVC 流程

    1. 检查是否为上传文件. 2. 通过HandlerMapping获取HandlerExecutionChain: DispatcherServlet 中包含:handlerMappings , 遍历 ...

  9. Python学习示例源码

    函数和函数式编程 函数定义: 函数调用: 过程定义: 过程调用: 面向过程的编程方法: """ 面向对象-----类------class 面向过程-----过程---- ...

  10. Heartbeats

    很少有人否定,这是一首天籁.凄美动听的声音,触动的,是真正的灵魂深处.所谓“仁者见仁智者见智”,但有些东西是共通的,比如,我们的内心会被同一样东西触动.在这首动听的歌曲中,体现出那男女之间平凡又伟大的 ...