YbtOJ-交换游戏【树链剖分,线段树合并】

正题


题目大意

给出两棵树,对于第一棵树的每一条边(x,y)(x,y)(x,y)询问有多少条在第二棵树上的边(u,v)(u,v)(u,v)与其交换(连接的序号相同)后两棵树依旧是一棵树。

1≤n≤2×1051\leq n\leq 2\times 10^51n2×105


解题思路

先只考虑一棵树的合法情况,对于第二棵树的边(u,v)(u,v)(u,v)交换过来合法的当且仅当(x,y)(x,y)(x,y)u→vu\rightarrow vuv路径上,同理的对于第二棵树合法当且仅当(u,v)(u,v)(u,v)x→yx\rightarrow yxy路径上。

那么考虑限制一个条件,第二个条件用数据结构查询。

我们把所有的(u,v)(u,v)(u,v)用树上差分挂在第一棵树的u→vu\rightarrow vuv路径上,然后遇到一条(u,v)(u,v)(u,v)我们让这棵树的这条边权值+1+1+1

这样我们就保证了处理到边(x,y)(x,y)(x,y)时有权值的只有在第一棵树上经过(x,y)(x,y)(x,y)u→vu\rightarrow vuv,那么至于第二个要求我们直接在第二棵树上查询x→yx\rightarrow yxy路径上的权值和。这个可以用树链剖分维护。

而树上差分的合并功能就用线段树合并就好了。

时间复杂度:O(nlog⁡2n)O(n\log^2n)O(nlog2n)


code

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#define mp(x,y) make_pair(x,y)
using namespace std;
const int N=2e5+10,U=20;
int n,cnt,depG[N],f[N][U],rt[N],ans[N];
int siz[N],fa[N],dep[N],son[N],top[N],id[N];
vector<pair<int,int> > G[N];
vector<int> T[N],v[N];
pair<int,int> e[N];
struct SegTree{int w[N<<5],ls[N<<5],rs[N<<5];void Change(int &x,int L,int R,int pos,int val){if(!x)x=++cnt;w[x]+=val;if(L==R)return;int mid=(L+R)>>1;if(pos<=mid)Change(ls[x],L,mid,pos,val);else Change(rs[x],mid+1,R,pos,val);}int Ask(int x,int L,int R,int l,int r){if(!x)return 0;if(L==l&&R==r)return w[x];int mid=(L+R)>>1;if(r<=mid)return Ask(ls[x],L,mid,l,r);if(l>mid)return Ask(rs[x],mid+1,R,l,r);return Ask(ls[x],L,mid,l,mid)+Ask(rs[x],mid+1,R,mid+1,r);}int Merge(int x,int y,int L,int R){if(!x||!y)return x|y;w[x]+=w[y];if(L==R)return x;int mid=(L+R)>>1;ls[x]=Merge(ls[x],ls[y],L,mid);rs[x]=Merge(rs[x],rs[y],mid+1,R);return x;}
}S;
void preset(int x,int fa){f[x][0]=fa;depG[x]=depG[fa]+1;for(int i=0;i<G[x].size();i++){int y=G[x][i].first;if(y==fa)continue;preset(y,x);}return;
}
int LCA(int x,int y){if(depG[x]<depG[y])swap(x,y);for(int i=U-1;i>=0;i--)if(depG[f[x][i]]>=depG[y])x=f[x][i];if(x==y)return x;for(int i=U-1;i>=0;i--)if(f[x][i]!=f[y][i])x=f[x][i],y=f[y][i];return f[x][0];
}
void dfs1(int x){dep[x]=dep[fa[x]]+1;siz[x]=1;for(int i=0;i<T[x].size();i++){int y=T[x][i];if(y==fa[x])continue;fa[y]=x;dfs1(y);siz[x]+=siz[y];if(siz[y]>siz[son[x]])son[x]=y;}return;
}
void dfs2(int x){id[x]=++cnt;if(son[x]){top[son[x]]=top[x];dfs2(son[x]);}for(int i=0;i<T[x].size();i++){int y=T[x][i];if(y==fa[x]||y==son[x])continue;top[y]=y;dfs2(y);}return;
}
int GetAns(int x,int y,int rt){int ans=0;while(top[x]!=top[y]){if(dep[top[x]]<dep[top[y]])swap(x,y);ans+=S.Ask(rt,1,n,id[top[x]],id[x]);x=fa[top[x]];}if(dep[x]>dep[y])swap(x,y);if(x!=y)ans+=S.Ask(rt,1,n,id[x]+1,id[y]);return ans;
}
void solve(int x,int fa,int ids){for(int i=0;i<G[x].size();i++){int y=G[x][i].first,id=G[x][i].second;if(y==fa)continue;solve(y,x,id);rt[x]=S.Merge(rt[x],rt[y],1,n);}if(ids){for(int i=0;i<v[x].size();i++){int p=abs(v[x][i]);int X=e[p].first,Y=e[p].second;if(dep[X]>dep[Y])swap(X,Y);S.Change(rt[x],1,n,id[Y],(v[x][i]>0)?1:-2);}ans[ids]=GetAns(fa,x,rt[x]);}return;
}
int main()
{freopen("exchange.in","r",stdin);freopen("exchange.out","w",stdout);scanf("%d",&n);for(int i=1;i<n;i++){int x,y;scanf("%d%d",&x,&y);G[x].push_back(mp(y,i));G[y].push_back(mp(x,i));}for(int i=1;i<n;i++){int x,y;scanf("%d%d",&x,&y);T[x].push_back(y);T[y].push_back(x);e[i]=mp(x,y);}preset(1,0);for(int j=1;j<U;j++)for(int i=1;i<=n;i++)f[i][j]=f[f[i][j-1]][j-1];for(int i=1;i<n;i++){int x=e[i].first,y=e[i].second,lca=LCA(x,y);v[x].push_back(i);v[y].push_back(i);v[lca].push_back(-i);}dfs1(1);top[1]=1;dfs2(1);solve(1,0,0);for(int i=1;i<n;i++)printf("%d ",ans[i]);return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/317562.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

模板:树状数组二分

所谓树状数组二分&#xff0c;就是在树状数组上进行二分 &#xff08;逃&#xff09; 解析 很巧妙 我们都知道可以在线段树上利用其本身平衡二叉的性质进行二分&#xff0c;很多时候能剩下一个log 但是树状数组其实也是可以二分的 说是二分&#xff0c;其实更像倍增 毕竟不…

微软收购Citus Data | 再次肯定对开源的承诺,并加速了Azure PostgreSQL的性能和扩展...

作者&#xff1a;Rohan Kumar 翻译&#xff1a;周宝峰 从左到右&#xff1a;微软开源关系数据库总经理Sudhakar Sannakkayala&#xff0c;Citus Data首席技术官兼联合创始人Ozgun Erdogan&#xff0c;Citus Data首席执行官兼联合创始人Umur Cubukcu&#xff0c;Citus Data工…

【CF1307F】Cow and Vacation(并查集+lca倍增)

description 点击查看题目 solution 考虑将边拆分&#xff0c;边长2\times 22 然后将kkk步以内可以互相走到的点用并查集合并在一起 同一个连通块的关键点可以相互走到 然后对于询问的两个城市&#xff0c;uuu向vvv走kkk步&#xff0c;vvv向uuu走kkk步&#xff0c;然后判断是…

AreYouBusy

AreYouBusy 题意: 给你n个工作集合&#xff0c;给你T的时间去做它们。给你m和s&#xff0c;说明这个工作集合有m件事可以做&#xff0c;它们是s类的工作集合&#xff08;s0,1,2&#xff0c;s0说明这m件事中最少得做一件&#xff0c;s1说明这m件事中最多只能做一件&#xff0c…

CF1404C:Fixed Point Removal(离线)(树状数组二分)

解析 写了不少线段树上二分&#xff0c;原来树状数组上也是可以二分的 首先如果ai>ia_i>iai​>i&#xff0c;那必然无法删除&#xff0c;下面只考虑ai<ia_i<iai​<i的情况 本题试图离线不难想到&#xff0c;但我一开始总是按照刻板思维尝试按序移动左端点&…

AT4439-[AGC028E]High Elements【结论,线段树】

正题 题目链接:https://www.luogu.com.cn/problem/AT4439 题目大意 给出1∼n1\sim n1∼n的排列aaa。求一个字典序最小的010101串sss满足将000对应位置按顺序取出成为序列AAA&#xff0c;剩下的成为序列BBB。 要求AAA和BBB的前缀最大值个数相同。 1≤n≤21051\leq n\leq 2\ti…

Docker最全教程——MongoDB容器化(十三)

上一节我们讲述了数据库容器化之持久保存数据&#xff0c;本节将讲诉MongoDB容器化实践&#xff0c;并且接下来将逐步讲解其他数据库&#xff08;MySql、Redis等等&#xff09;的容器化实践&#xff0c;然后将讲诉一些分布式架构的项目实践。由于实践需要花费大量的时间&#x…

一些数学小公式/定理的证明

文章目录定理①&#xff1a;类欧几里得算法公式①&#xff1a;等比数列求和②&#xff1a;等差数列一次方和③&#xff1a;等差数列二次方和结论①&#xff1a;n&11⇒3∣(2n−2)n\&11\Rightarrow 3|(2^n-2)n&11⇒3∣(2n−2)②&#xff1a;1222...n2n(n1)(2n1)61^22…

背包模型题目集合

文章目录背包模型01背包AcWing 423. 采药AcWing 1024. 装箱问题Luogu 2925 干草出售Proud Merchants完全背包P1616 疯狂的采药P1853 投资的最大效益Piggy-Bank多重背包Luogu P1776 宝物筛选HDU 1059 Dividing混合背包P1833 樱花二维费用背包问题P1507 NASA的食物计划HDU 2159 F…

CF1063F-String Journey【SAM,线段树】

正题 题目链接:https://www.luogu.com.cn/problem/CF1063F 题目大意 给出一个字符串&#xff0c;求选出kkk个不交子串满足按照起始位置排序后&#xff0c;满足下一个是上一个的真子串。 求kkk的最大值。 1≤n≤51051\leq n\leq 5\times 10^51≤n≤5105 解题思路 首先我们肯…

CF1406D:Three Sequences(贪心、构造)

解析 本题说明了样例的重要性 完全可以通过仔细观察样例得出一些结论 首先最大值显然就是max⁡(b1,cn)\max(b_1,c_n)max(b1​,cn​) 考虑最优策略 如果a上升了&#xff0c;就让b上升 因为假设前面都拼的严丝合缝了&#xff0c;让c上升前面全得上升&#xff0c;肯定会对答案有…

在.NET Core中使用Exceptionless分布式日志收集框架

一.Exceptionless简介Exceptionless 是一个开源的实时的日志收集框架&#xff0c;它可以应用在基于 ASP.NET&#xff0c;ASP.NET Core&#xff0c;Web Api&#xff0c;Web Forms&#xff0c;WPF&#xff0c;Console&#xff0c;MVC 等技术栈的应用程序中&#xff0c;并且提供了…

YbtOJ-选点构形【欧拉函数】

正题 题目链接:https://www.ybtoj.com.cn/contest/351/problem/1 题目大意 一个圆上&#xff0c;你需要在3∼n3\sim n3∼n中选出kkk个作为aia_iai​&#xff0c;然后再圆上选择最少的点使得对于每个aia_iai​你都能用选出的点连成一个正aia_iai​边形。 k2≤n≤106k2\leq n\l…

CF1406E:Deleting Numbers(构造、根号分块)

解析 打表发现1e5以内的质因子是9592个 就是它没错了 容易想到枚举因子判断答案是否异常来判断是否包含该质因子 但是这个方法在最小质因子处是不奏效的 那么如何找到最小的质因子呢&#xff1f; 考虑把所有的质因子分成m\sqrt mm​块 然后每扫完一块&#xff0c;问一下 (A,…

test1 3-15 模拟赛1

文章目录考试复盘matrixsetstring考试复盘 首先先说T1T1T1&#xff0c;嗯&#xff0c;发现了列是相互独立的&#xff0c;所以分开考虑了 但是实在没想到线性基&#xff0c;就顺着自己的思路硬搞了505050跑路 老实说&#xff0c;505050分的部分分写得都是迷迷糊糊的&#xff0c;…

华为云提供针对Nuget包管理器的缓存加速服务测试

在Visual Studio 2013、2015、2017中&#xff0c;使用的是Nuget包管理器对第三方组件进行管理升级的。而且 Nuget 是我们使用.NET Core的一项基础设施&#xff0c;.NET的软件包管理器NuGet.org是一项面向全球用户搭建的服务&#xff0c;不论用户身在何处&#xff0c;NuGet.org都…

Consumer

Consumer 题意&#xff1a; n个游戏机&#xff0c;有w钱 每个游戏机上有游戏&#xff0c;每个游戏有价格和娱乐值&#xff0c;游戏机有价格&#xff0c;没有娱乐值&#xff0c;玩游戏必须要用对应的游戏机&#xff0c;问娱乐值最大是多少 题解&#xff1a; 有依赖关系的背包…

Loj#6405-「ICPC World Finals 2018」征服世界【模拟费用流,左偏树】

正题 题目链接:https://loj.ac/p/6405 题目大意 给出nnn个点的一棵树&#xff0c;每个点有xix_ixi​个军队&#xff0c;需要yiy_iyi​个军队&#xff0c;你可以移动军队&#xff0c;求使得满足所有点要求的情况下&#xff0c;军队移动路径和的最小值。 1≤n≤2500001\leq n\l…

兰道定理(竞赛图)

所谓兰道定理&#xff0c;就是兰道定下的道理 &#xff08;逃&#xff09; 解析 每条边被规定了方向的完全图叫做竞赛图 竞赛图中&#xff0c;设每个点的出度为uiu_iui​ 显然有&#xff1a; ∑uin(n−1)2\sum u_i\dfrac{n\times(n-1)}{2}∑ui​2n(n−1)​ 而兰道定理的内容是…

test2 3-16 2021 模拟赛two

文章目录考试复盘染色问题芬威克树礼物考试复盘 先说T1T1T1 染色&#xff0c;以为是道数学题&#xff0c;推了有一会儿的公式&#xff0c;从颜色1到颜色m&#xff0c;感觉是dpdpdp转移 发现颜色重叠的方案可以转化为另外一种相邻不重叠的染色 但是推到颜色4的时候就发现自己…