题意:一棵树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. 更改vim高亮括号匹配颜色

    vim括号匹配高亮显示在vim7.4版本, 默认就是开启的. 但是默认的括号匹配 高亮的颜色是浅蓝色, 在亮瞎眼的同时, 严重影响我们写代码, 最明显的感受 就是, 连续打出一对括号, 接下来不仔细看 ...

  2. MySQL,sqlalchemy

    Mariadb 数据库是一堆表的集合 主键 外键 索引 安装: Centos7 [root@host]# mysqladmin -u root password "new_password& ...

  3. windows安装oracle client 18c 和plsql工具

    安装须知: (1)安装平台选择.linux/windows (2)软件位数选择.32/64,如果你的plsql工具是32位,那么你就安装32位客户端,如果是64位,你就安装64位客户端. 安装过程: ...

  4. 新一批创业者金矿,iclap谁与争锋

    19世纪,美国西部开发,无数拓荒者涌入,并最终因金矿的发现形成了淘金热.而当无数人埋头寻找黄金之时,有一个人却抬起头看到了潜藏在无数淘金者身上的金矿-这个人就是牛仔裤的发明者,Levi’s的创始人-李 ...

  5. 如何在idea中设置 jsp 内容修改以后,立即生效而不用重新启动服务?

    点击 run---->edit configuration--->

  6. 基于Python操作redis介绍

    (注:本文部分内容摘自互联网,由于作者水平有限,不足之处,还望留言指正.) 毕业前的最后一个学期(2016.03),龙哥结婚了.可是总有些人喜欢嘲笑别人,调侃我.当时我就理直气壮的告诉他们,等龙哥孩子 ...

  7. python3_requests模块详解

    1.模块说明 requests是使用Apache2 licensed 许可证的HTTP库. 用python编写. 比urllib2模块更简洁. Request支持HTTP连接保持和连接池,支持使用co ...

  8. Java基础知识---continue

    一:java概述: 1991 年Sun公司的James Gosling等人开始开发名称为 Oak 的语言,希望用于控制嵌入在有线电视交换盒.PDA等的微处理器: 1994年将Oak语言更名为Java: ...

  9. mysql 手动安装和管理

    版本:5.7.10 my.ini简单配置 [client] default-character-set=utf8 [mysqld] port = 3306 basedir =D:/programs/M ...

  10. hello java !

    我对于计算机性编程性质的课程一直没有很好的悟性,但功夫不服有心,最近自己学习视频课程,随时关注娄老师的博客,慢慢的对于java编程有了新的认识,也用eclipse软件进行了简单java的编译. 了解的 ...