题意:一棵树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. 解析button和input type=”button”的区别

    一.定义和用法 <button> 标签定义的是一个按钮. 在 button 元素内部,可以放置文本或图像.这是<button>与使用 input 元素创建的按钮的不同之处. 二 ...

  2. HDU1115&&POJ1385Lifting the Stone(求多边形的重心)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1115# 大意:给你个n,有n个点,然后给你n个点的坐标,求这n个点形成的多边形的重心的坐标. 直接套模 ...

  3. Mysql—(1)—

    sql语句 sql是Structured Query Language(结构化查询语言)的缩写.SQL是专为数据库而建立的操作命令集,是一种功能齐全的数据库语言. 在使用它时,只需要发出“做什么”的命 ...

  4. ORM中的related_name

    ORM 的反向查找(related_name) 先定义两个模型,一个是A,一个是B,是一对多的类型. class A(models.Model): name= models.CharField('名称 ...

  5. The 15th UESTC Programming Contest Preliminary C - C0ins cdoj1554

    地址:http://acm.uestc.edu.cn/#/problem/show/1554 题目: C0ins Time Limit: 3000/1000MS (Java/Others)     M ...

  6. SQL Server怎么备份数据库

    1.打开 2.选择需要备份的数据库,右键 Tasks 3.Tasks的下垃菜单 4.add选备份路径,添加名字 5.OK

  7. HTTP服务器(3)

    功能完整的HTTP服务器 导语 这个一个功能完备的HTTP服务器.它可以提供一个完整的文档输,包括图像,applet,HTML文件,文本文件.它与SingleFileHttpServer非常相似,只不 ...

  8. linux上mysql访问:Access denied for user 'agtipay'@'iZm5ebiyb4f90ga9xiycgsZ' (using password: YES)

    公司的聚合支付测试环境出了一个问题(agtipay用户访问数据的时候出现如题错误),快搞死我两天时间(原谅技术不才),如题.首先明确一下问题: 1.访问拒绝,说明数据库连接这里有问题,数据库连接访问拒 ...

  9. JS正则表达式从入门到入土(10)—— 字符串对象方法

    字符串对象方法 search方法 String.prototype.search(reg) search方法用于检索字符串中指定的子字符串,或检索与正则表达式相匹配的子字符串,方法返回第一个匹配结果的 ...

  10. mybatis关联配置(一对多配置)

    敲代码也有不少日子了,今天碰到个需求,就是定时器生成一张表,但是这个表的某些数据是从另外两张表中拿到的,定外两张表又是一对多的关系,想着咋在一个接口就能敲出来,大概结构如下 然后需要a表的数据(比如张 ...