UVALive - 6712 lca+dfs序线段树
题意:一棵树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序线段树的更多相关文章
- Educational Codeforces Round 6 E dfs序+线段树
题意:给出一颗有根树的构造和一开始每个点的颜色 有两种操作 1 : 给定点的子树群体涂色 2 : 求给定点的子树中有多少种颜色 比较容易想到dfs序+线段树去做 dfs序是很久以前看的bilibili ...
- 【BZOJ-3252】攻略 DFS序 + 线段树 + 贪心
3252: 攻略 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 339 Solved: 130[Submit][Status][Discuss] D ...
- Codeforces 343D Water Tree(DFS序 + 线段树)
题目大概说给一棵树,进行以下3个操作:把某结点为根的子树中各个结点值设为1.把某结点以及其各个祖先值设为0.询问某结点的值. 对于第一个操作就是经典的DFS序+线段树了.而对于第二个操作,考虑再维护一 ...
- BZOJ2434 [Noi2011]阿狸的打字机(AC自动机 + fail树 + DFS序 + 线段树)
题目这么说的: 阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机.打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P'两个字母.经阿狸研究发现,这个打字机是这样工作的: 输入小 ...
- POJ 3321 DFS序+线段树
单点修改树中某个节点,查询子树的性质.DFS序 子树序列一定在父节点的DFS序列之内,所以可以用线段树维护. 1: /* 2: DFS序 +线段树 3: */ 4: 5: #include < ...
- 【XSY2667】摧毁图状树 贪心 堆 DFS序 线段树
题目大意 给你一棵有根树,有\(n\)个点.还有一个参数\(k\).你每次要删除一条长度为\(k\)(\(k\)个点)的祖先-后代链,问你最少几次删完.现在有\(q\)个询问,每次给你一个\(k\), ...
- F - Change FZU - 2277 (DFS序+线段树)
题目链接: F - Change FZU - 2277 题目大意: 题意: 给定一棵根为1, n个结点的树. 有q个操作,有两种不同的操作 (1) 1 v k x : a[v] += x, a[v ' ...
- BZOJ4551[Tjoi2016&Heoi2016]树——dfs序+线段树/树链剖分+线段树
题目描述 在2016年,佳媛姐姐刚刚学习了树,非常开心.现在他想解决这样一个问题:给定一颗有根树(根为1),有以下 两种操作:1. 标记操作:对某个结点打上标记(在最开始,只有结点1有标记,其他结点均 ...
- BZOJ1103 [POI2007]大都市meg dfs序 线段树
欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ1103 题意概括 一棵树上,一开始所有的边权值为1,我们要支持两种操作: 1. 修改某一条边的权值为 ...
随机推荐
- UVA+POJ中大数实现的题目,持续更新(JAVA实现)
UVA10494:If We Were a Child Again 大数除法加取余 import java.util.Arrays; import java.util.Scanner; import ...
- PAT 1077 Kuchiguse [一般]
1077 Kuchiguse (20 分) The Japanese language is notorious for its sentence ending particles. Personal ...
- MySQL学习之——锁(转)
锁,在现实生活中是为我们想要隐藏于外界所使用的一种工具.在计算机中,是协调多个进程或县城并发访问某一资源的一种机制.在数据库当中,除了传统的计算资源(CPU.RAM.I/O等等)的争用之外,数据也是一 ...
- C语言赋初始值
- nginx日志输出,https,ssl
日志输出(浏览器直接访问)缺省安装下,浏览器是无法访问日志的,需要在编译的时候附带参数安装这些模块 ./configure --prefix=/usr/local/nginx --with-http_ ...
- DevStore分享:详析消费者十大心理学
做生意,其实就是一个恋爱的过程,让用户找到你.了解你,爱上你.而这个过程中的关键点就是用户.只要与用户心理相关的,那么就会影响到他们的购买决策.而作为卖方的你,就应该了解消费者心里面在想些什么. 第一 ...
- 51nod 1391 01串(hash+DP)
题目链接题意:给定一个01串S,求出它的一个尽可能长的子串S[i..j],满足存在一个位置i<=x <=j, S[i..x]中0比1多,而S[x + 1..j]中1比0多.求满足条件的最长 ...
- NodeJS中间层搭建
前言 最近碰了个壁,公司开发的一个新项目里我大胆地提出要前后端完全分离,用JavaScript模板引擎.ajax.路由等技术替代繁琐的前后端混合的业务逻辑,项目进行到一半前辈提出来仅仅靠前端的力量无法 ...
- 自我管理--拖延 vs 心理
案例1:你在销售公司产品,需要更多客户,这时你收到一条短信,说对你们产品感兴趣,让你马上发送详细资料看看,语气颇为傲慢.你有点恼火,这个人一点都不客气,于是两小时后你才发送过去. 案例2:这个月的 ...
- 20145301 实验三 "敏捷开发与XP实践"
20145301 实验三 "敏捷开发与XP实践" 课程:Java程序设计 班级:1453 指导教师:娄嘉鹏 实验日期:2016.04.22 实验名称:敏捷开发与XP实践 一.实验 ...