P7735-[NOI2021]轻重边【树链剖分,线段树】

前言

之前线上赛就A的题现在才写博客
请添加图片描述


正题

题目链接:https://www.luogu.com.cn/problem/P7735


题目大意

nnn个点的一棵树,开始所有边都是轻边,mmm次操作。

  1. x→yx\rightarrow yxy路径上所有点连接的重边都变为轻边,然后再把路径上的边变成重边。
  2. 询问一条路径上的重边数量。

1≤T≤3,1≤n,m≤1051\leq T\leq 3,1\leq n,m\leq 10^51T3,1n,m105


解题思路

前随便找个点当根,我们用每个点去储存它连向它父节点边的信息。

然后考虑如何进行操作,发现是树上的路径操作,考虑树链剖分。

*为了方便描述我们将树链剖分的轻重边用加粗进行描述

首先我们可以先把路径上所有边(所对应的点储存的信息)都改成重边,那么问题就出在我们如何把连接的重边改成轻边。

暴力修改这些边显然不可行,我们注意到树链剖分后的我们可以方便的修改重边,而一条路径上的轻边路径不多,所以我们可以考虑只统一维护重边信息,而轻边信息我们可以在查询的时候再处理。

那么做法就很显然了,对于重边的信息我们用线段树修改,而对于轻边,我们再开一个线段树记录每个端点上次被覆盖的路径编号。

如果轻边所连接的两个端点是被不同路径覆盖的,那么这条边就是轻边,不然就是重边。

时间复杂度:O(mlog⁡2n)O(m\log^2 n)O(mlog2n)


code

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<cctype>
using namespace std;
const int N=1e5+10;
int read(){int x=0,f=1;char c=getchar();while(!isdigit(c)){if(c=='-')f=-f;c=getchar();}while(isdigit(c)){x=(x<<1)+(x<<3)+c-48;c=getchar();}return x*f;
}
struct node{int to,next;
}a[N<<1];
int T,n,m,cnt,tot,ls[N],fa[N],dep[N];
int rfn[N],ed[N],siz[N],son[N],top[N],id[N];
void addl(int x,int y){a[++tot].to=y;a[tot].next=ls[x];ls[x]=tot;return;
}
void dfs(int x){rfn[x]=++cnt;siz[x]=1;dep[x]=dep[fa[x]]+1;for(int i=ls[x];i;i=a[i].next){int y=a[i].to;if(y==fa[x])continue;fa[y]=x;dfs(y);siz[x]+=siz[y];if(siz[y]>siz[son[x]])son[x]=y;}ed[x]=cnt;return;
}
void dFs(int x){id[x]=++cnt;if(son[x]){top[son[x]]=top[x];dFs(son[x]);}for(int i=ls[x];i;i=a[i].next){int y=a[i].to;if(y==fa[x]||y==son[x])continue;top[y]=y;dFs(y);}return;
}
struct SegTree{int w[N<<2],lazy[N<<2];void Clear(){memset(w,0,sizeof(w));memset(lazy,0,sizeof(lazy));return;}void Downdata(int x,int l,int r){if(!lazy[x])return;int mid=(l+r)>>1;w[x*2]=(mid-l+1)*lazy[x];w[x*2+1]=(r-mid)*lazy[x];lazy[x*2]=lazy[x*2+1]=lazy[x]; lazy[x]=0;return;}int Ask(int x,int L,int R,int l,int r){if(L==l&&R==r)return w[x];int mid=(L+R)>>1;Downdata(x,L,R);if(r<=mid)return Ask(x*2,L,mid,l,r);if(l>mid)return Ask(x*2+1,mid+1,R,l,r);return Ask(x*2,L,mid,l,mid)+Ask(x*2+1,mid+1,R,mid+1,r);}void Change(int x,int L,int R,int l,int r,int val){if(L==l&&R==r){w[x]=(R-L+1)*val;lazy[x]=val;return;}int mid=(L+R)>>1;Downdata(x,L,R);if(r<=mid)Change(x*2,L,mid,l,r,val);else if(l>mid)Change(x*2+1,mid+1,R,l,r,val);else Change(x*2,L,mid,l,mid,val),Change(x*2+1,mid+1,R,mid+1,r,val);w[x]=w[x*2]+w[x*2+1];}
}Tw,Tl;
void Updata(int x,int y,int pos){while(top[x]!=top[y]){if(dep[top[x]]<dep[top[y]])swap(x,y);if(top[x]!=x)Tw.Change(1,1,n,id[top[x]]+1,id[x],1);Tl.Change(1,1,n,id[top[x]],id[x],pos);if(son[x])Tw.Change(1,1,n,id[x]+1,id[x]+1,0);x=fa[top[x]];}if(dep[x]>dep[y])swap(x,y);Tl.Change(1,1,n,id[x],id[y],pos);if(id[x]!=id[y])Tw.Change(1,1,n,id[x]+1,id[y],1);if(son[y])Tw.Change(1,1,n,id[y]+1,id[y]+1,0);if(top[x]!=x)Tw.Change(1,1,n,id[x],id[x],0);
}
bool check(int x){int p=Tl.Ask(1,1,n,id[x],id[x]);if(!p)return 0;return (p==Tl.Ask(1,1,n,id[fa[x]],id[fa[x]]));
}
int Ask(int x,int y){int ans=0;while(top[x]!=top[y]){if(dep[top[x]]<dep[top[y]])swap(x,y);ans+=Tw.Ask(1,1,n,id[top[x]],id[x]);x=top[x];ans+=check(x);x=fa[x];}if(dep[x]>dep[y])swap(x,y);if(id[x]!=id[y])ans+=Tw.Ask(1,1,n,id[x]+1,id[y]);return ans;
}
int main()
{T=read();while(T--){tot=0;memset(ls,0,sizeof(ls));memset(fa,0,sizeof(fa));memset(son,0,sizeof(son));Tl.Clear();Tw.Clear();n=read();m=read();for(int i=1;i<n;i++){int x=read(),y=read();addl(x,y);addl(y,x);}cnt=0;dfs(1);cnt=0;top[1]=1;dFs(1);cnt=0;while(m--){int op=read(),x=read(),y=read();if(op==1)++cnt,Updata(x,y,cnt);else cout<<Ask(x,y)<<'\n';}}return 0;
}

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

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

相关文章

.NET Core实战项目之CMS 第十六章 用户登录及验证码功能实现

前面为了方便我们只是简单实现了基本业务功能的增删改查&#xff0c;但是登录功能还没有实现&#xff0c;而登录又是系统所必须的&#xff0c;得益于 ASP.NET Core的可扩展性因此我们很容易实现我们的登录功能。今天我将带着大家一起来实现下我们的ASP.NET Core2.2开发的CMS系统…

CF508D Tanya and Password(欧拉回路)

解析 之前模拟考过的一道题 把字符串当成前后缀之间的连边即可 注意即使图的度数符合要求&#xff0c;也可能由于不连通而无解&#xff0c;需要再特判一下 #include<bits/stdc.h> using namespace std; #define ll long long #define ull unsigned long long const int…

[HEOI2016/TJOI2016]字符串 (后缀数组+主席树+二分)

description 佳媛姐姐过生日的时候&#xff0c;她的小伙伴从某东上买了一个生日礼物。生日礼物放在一个神奇的箱子中。箱子外边写了一个长为 n 的字符串 s&#xff0c;和 m 个问题。佳媛姐姐必须正确回答这 m 个问题&#xff0c;才能打开箱子拿到礼物&#xff0c;升职加薪&…

[SDOI2014]旅行

[SDOI2014]旅行 题意&#xff1a; n个城市&#xff0c;n-1条边&#xff0c;任意两个城市互通&#xff0c;每个城市有所信奉的宗教和城市评级&#xff0c;有四种指令&#xff1a; 1.将城市x的居民改信为c教 2.将城市x的评级调整为w 3.统计x到y&#xff0c;路上所有的城市的评级…

YbtOJ-染色计划【树链剖分,线段树,tarjan】

正题 题目大意 给出nnn个点的一棵树&#xff0c;每个点有个颜色aia_iai​&#xff0c;你每次可以选择一个颜色全部变成另一个颜色。 求最少多少次操作可以把一种颜色变成一个完整的连通块。 1≤k≤n≤21051\leq k\leq n\leq 2\times 10^51≤k≤n≤2105 解题思路 考虑如果我们…

张高兴的 .NET Core IoT 入门指南:环境配置、Blink、部署

如何在 Raspberry Pi 的 Raspbian 上构建使用 GPIO 引脚的 IoT 程序&#xff1f;你可能会回答使用 C 或 Python 去访问 Raspberry Pi 的引脚。现在&#xff0c;C# 程序员可以使用 .NET Core 在 Raspbian(Linux) 上构建 IoT 应用程序。只需要引入 System.Device.GPIONuGet 包即可…

CF183C:Diverse Permutation(构造)

解析 首先考虑如何构造kn-1的情况 发现令排列为1,n,2,n-1…即可 那么在k不等于n-1时 只需要让前k项与上面的序列相同&#xff0c;后面公差为1即可 代码 #include<bits/stdc.h> using namespace std; #define ll long long #define ull unsigned long long const int N…

CF603E-Pastoral Oddities【CDQ分治,可撤销并查集】

正题 题目链接:https://www.luogu.com.cn/problem/CF603E 题目大意 开始时有nnn个点&#xff0c;没有边。 依次加入mmm条带权的边&#xff0c;每次加入后询问是否存在一个边集&#xff0c;满足每个点的度数均为奇数&#xff0c;求使得这个边集的最大权值最小。 1≤n≤105,1≤…

2020ICPC 江西省大学生程序设计竞赛

2020ICPC 江西省大学生程序设计竞赛

在AspNetMvc中使用日志面板. Logdashboard 1.1beta

Logdashboard是Net下的日志面板,它支持AspNet与AspNetCore项目。关于更多LogDashboard的介绍请看这里--使用logdashboard查看可视化日志。就在刚刚LogDashboard发布了1.1的beta版,在这个版本中有以下变化https://github.com/liangshiw/LogDashboard/releases支持NetFramework的…

【正睿2021寒假省选第二轮集训 day 1】令牌生成 (组合数+二分)

description solution 打表yyds 其实符合条件的个数跟nnn&#xff08;非题目中的意思&#xff09;有着等差数列公式的千丝万缕关系 所以可以二分出具体值 最后答案的取值范围一定是长成[,)[,)[,)&#xff0c;左闭右开的形式的 而且两个边界一定是只差了最小的那个111&#xff…

CF600F:Edge coloring of bipartite graph(二分图、构造)

解析 首先大胆猜结论&#xff1a;答案就是最大的点度数 考虑如何构造 设一个点联通的边的颜色集合为S&#xff0c;由题意得S中的元素不可重 假设新加入一条边(u,v) 设c1mex(Su),c2mex(Sv)c1mex(S_u),c2mex(S_v)c1mex(Su​),c2mex(Sv​) 如果c1等于c2&#xff0c;直接连就行了…

CF464E-The Classic Problem【最短路,主席树】

正题 题目链接:https://www.luogu.com.cn/problem/CF464E 题目大意 nnn个点mmm条边的一张无向图&#xff0c;第iii条边长度为2xi2^{x_i}2xi​&#xff0c;求sss到ttt的最短路。 1≤n≤105,0≤m,xi≤1051\leq n\leq 10^5,0\leq m,x_i\leq 10^51≤n≤105,0≤m,xi​≤105 解题思路…

.NETStandard FreeSql v0.0.9 功能预览

年关将至&#xff0c;首页技术含量文章真是越来越少&#xff0c;理解大家盼着放假过年&#xff0c;哥们我何尝不是&#xff0c;先给大家拜个早年。兄弟我从11月底发了神经&#xff0c;开启了 ORM 功能库的开发之旅&#xff0c;历时两个月编码和文档整理&#xff0c;目前预览版本…

【CF868F】Yet Another Minimization Problem (决策单调性优化dp+分治)

description 点击查看题目 solution code 设dpi,jdp_{i,j}dpi,j​&#xff1a;把前iii个数划分jjj段的最小花费&#xff0c;wi,jw_{i,j}wi,j​&#xff1a;[i,j][i,j][i,j]划分为一段的花费 dpi,jmin(dp[k][j−1]w[k1][i])&#xff0c;k<idp_{i,j}min(dp[k][j-1]w[k1][i…

YbOJ-网格序列【拉格朗日插值】

正题 题目大意 有一个nmn\times mnm的网格&#xff0c;在上面填上[1,k][1,k][1,k]的数字&#xff0c;定义两个长度为nnn的序列ai,bia_i,b_iai​,bi​分别表示每一行/每一列的最大值。 求有多少种不同的合法a,ba,ba,b对。 1≤n,m≤106,1≤k≤1091\leq n,m\leq 10^6,1\leq k\le…

CF720C Homework(构造)(暴力)

解析 本题的关键是暴力与构造结合的思想 本题一排排往上填的想法不难得出&#xff0c;但是在列数较小的时候就会GG 所以考虑在n>5&#xff0c;m<5时&#xff0c;交换n&#xff0c;m&#xff0c;显然问题还是等价的 如果nm均小于5&#xff0c;就直接暴力dfs解决 在最后的…

第十二届蓝桥杯C++赛后感

文章目录A 空间卡片直线货物摆放路径时间显示G砝码称重H杨辉三角形双向排列J括号序列注&#xff1a;有些代码忘了考试时怎么写的了&#xff0c;&#xff08;我也懒得重新写&#xff09;&#xff0c;所以很多题的代码是acwing蓝桥杯讲解里的&#xff0c;我对其进行注释和修改A 空…

SeaweedFS在.net core下的实践方案

一直对分布式的文件储存系统很感兴趣&#xff0c;最开始关注淘宝的TFS&#xff08;Taobao File System&#xff09;&#xff0c;好像搁浅了&#xff0c;官方地址无法访问&#xff0c;github上面&#xff0c;各种编译问题&#xff0c;无意间发现了SeaweedFS链接seaweedfs测试了一…

[C++ STL algorithm] lower_bound、upper_bound、unique的本质

lower_bound&#xff1a;返回第一个大于等于查找值的地址upper_bound&#xff1a;返回第一个严格大于查找值的地址 使用这两个函数需要的头文件 #include <algorithm> using namespace std;要求数组必须是有序/单调的 lower_bound lower_bound( a 1, a n 1, x );意…