洛谷 4115 Qtree4——链分治
题目:https://www.luogu.org/problemnew/show/P4115
论文:https://wenku.baidu.com/view/1bc2e4ea172ded630b1cb602.html
重链剖分,分别用线段树维护每条重链。线段树叶子的信息是该点轻孩子的信息;线段树区间的信息是考虑重链的一个区间以及附带的轻孩子们的信息。
修改一个点,改它所在的重链的信息。祖先的每条重链都有一个点的 “轻孩子信息” 改变了,改一下那个位置的值,更新它的线段树,再用该重链的信息作为轻孩子更新更上面的重链。
本题每个点要维护的是 “向下以白点为端点的最长链” 和 “向下以白点为端点的次长链” 。用可删堆维护。
线段树区间维护 “从左边开始、以白点结束的最长链” 、 “从右边开始、以白点结束的最长链” 、 “中间一条两端点都是白点的最长链” 。前两个信息是为了更新第三个信息。
每条重链的答案放进全局可删堆中。
注意求 “次长链” 的时候,自己是先把堆顶拿出来,再看剩下的堆的堆顶。要注意再看之前先用删除堆更新一下!
预处理的时候,自己想一个一个插入。在 pshp 的时候要用到兄弟的 fl , fr , pr , sc 等信息。所以得先把线段树整个建出来,不能有些孩子是空的就开始 pshp 。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<queue> #define ls Ls[cr] #define rs Rs[cr] using namespace std; int rdn() {int ret=0;bool fx=1;char ch=getchar();while(ch>'9'||ch<'0'){if(ch=='-')fx=0;ch=getchar();}while(ch>='0'&&ch<='9')ret=ret*10+ch-'0',ch=getchar();return fx?ret:-ret; } int Mx(int a,int b){return a>b?a:b;} int Mn(int a,int b){return a<b?a:b;} const int N=1e5+5,M=2e5+5,INF=1e9,Lm=-1e8; int n,hd[N],xnt,to[M],nxt[M],w[M]; bool col[N]; int siz[N],son[M],dep[N],fa[N],fw[N],top[N]; int dis[N],dp2[N],lm[N],tot,rt[N],Ls[M],Rs[M]; int dy[N],fl[M],fr[M],mx[M],pr[M],sc[M]; priority_queue<int> q[N],dq[N],ans,dans; int Dis(int x,int y){return dp2[y]-dp2[x];} void frs(int x) {while(dq[x].size()&&q[x].top()==dq[x].top())q[x].pop(), dq[x].pop(); } void pshp(int cr) {pr[cr]=pr[ls]; sc[cr]=sc[rs];fl[cr]=Mx(fl[ls],Dis(pr[cr],pr[rs])+fl[rs]);fr[cr]=Mx(fr[rs],Dis(sc[ls],sc[cr])+fr[ls]);mx[cr]=Mx(Dis(sc[ls],pr[rs])+fr[ls]+fl[rs],Mx(mx[ls],mx[rs])); } void build(int l,int r,int &cr) {cr=++tot;fl[cr]=fr[cr]=mx[cr]=-INF;pr[cr]=dy[l]; sc[cr]=dy[r];if(l==r)return; int mid=l+r>>1;build(l,mid,ls); build(mid+1,r,rs); } void updt(int l,int r,int cr,int p,int k) {if(l==r){fl[cr]=fr[cr]=dis[k]; pr[cr]=sc[cr]=k;if(!q[k].size()){ mx[cr]=-INF; return;}q[k].pop(); frs(k);// int d2=-INF;if(q[k].size())d2=q[k].top();if(!col[k])mx[cr]=Mx(dis[k]+d2,Mx(dis[k],d2));//col[k] not col[cr]!!else mx[cr]=dis[k]+d2;q[k].push(dis[k]);return;}int mid=l+r>>1;if(p<=mid)updt(l,mid,ls,p,k); else updt(mid+1,r,rs,p,k);pshp(cr); } void add(int x,int y,int z) {to[++xnt]=y;nxt[xnt]=hd[x];hd[x]=xnt;w[xnt]=z;} void dfs(int cr,int f) {dep[cr]=dep[f]+1; dp2[cr]=dp2[f]+fw[cr];fa[cr]=f; siz[cr]=1;for(int i=hd[cr],v;i;i=nxt[i])if((v=to[i])!=f){fw[v]=w[i]; dfs(v,cr); siz[cr]+=siz[v];if(siz[v]>siz[son[cr]])son[cr]=v;} } int Ps(int cr){return dep[cr]-dep[top[cr]]+1;} void dfsx(int cr,int f) {if(son[cr])top[son[cr]]=top[cr],dfsx(son[cr],cr);for(int i=hd[cr],v;i;i=nxt[i])if((v=to[i])!=f&&v!=son[cr]){top[v]=v;dfsx(v,cr);if(fl[rt[v]]>Lm)q[cr].push(fl[rt[v]]+w[i]);}if(!col[cr])q[cr].push(0);if(q[cr].size())dis[cr]=q[cr].top(); else dis[cr]=-INF;int p=Ps(cr),tp=top[cr];if(p>lm[tp]){lm[tp]=p;for(int i=p,k=cr;i;i--,k=fa[k])dy[i]=k;build(1,p,rt[tp]);}updt(1,lm[tp],rt[tp],p,cr);if(tp==cr)ans.push(mx[rt[cr]]); } void chg(int cr) {col[cr]=!col[cr];if(!col[cr])q[cr].push(0); else dq[cr].push(0);int x=top[cr]; frs(cr);if(q[cr].size())dis[cr]=q[cr].top(); else dis[cr]=-INF;dans.push(mx[rt[x]]);if(fa[x])dq[fa[x]].push(fl[rt[x]]+fw[x]);updt(1,lm[x],rt[x],Ps(cr),cr);ans.push(mx[rt[x]]);if(fa[x])q[fa[x]].push(fl[rt[x]]+fw[x]);while(fa[x]){cr=fa[x]; x=top[cr]; frs(cr);if(q[cr].size())dis[cr]=q[cr].top(); else dis[cr]=-INF;dans.push(mx[rt[x]]);if(fa[x])dq[fa[x]].push(fl[rt[x]]+fw[x]);updt(1,lm[x],rt[x],Ps(cr),cr);ans.push(mx[rt[x]]);if(fa[x])q[fa[x]].push(fl[rt[x]]+fw[x]);} } int main() {n=rdn();for(int i=1,u,v,z;i<n;i++){u=rdn();v=rdn();z=rdn();add(u,v,z);add(v,u,z);}dfs(1,0); top[1]=1; dfsx(1,0);int Q=rdn(); char ch;int x;while(Q--){cin>>ch;if(ch=='A'){while(dans.size()&&ans.top()==dans.top())ans.pop(),dans.pop();if(ans.top()<Lm)puts("They have disappeared.");else printf("%d\n",ans.top());}else{ x=rdn(); chg(x);}}return 0; }
转载于:https://www.cnblogs.com/Narh/p/10776851.html
洛谷 4115 Qtree4——链分治相关推荐
- 洛谷 P1127 词链
词链 题目链接 题目描述 如果单词 X X X 的末字母与单词 Y Y Y 的首字母相同,则 X X X 与 Y Y Y 可以相连成 X . Y X.Y X.Y.(注意: X X X. Y Y Y 之 ...
- 洛谷T44252 线索_分治线段树_思维题
分治线段树,其实就是将标记永久化,到最后再统一下传所有标记. 至于先后顺序,可以给每个节点开一个时间戳. 一般地,分治线段树用于离线,只查询一次答案的题目. 本题中,标记要被下传 222 次. Cod ...
- 洛谷 4178 Tree——点分治
题目:https://www.luogu.org/problemnew/show/P4178 点分治.如果把每次的 dis 和 K-dis 都离散化,用树状数组找,是O(n*logn*logn),会T ...
- 洛谷P1127 词链 欧拉路问题
题目描述: 如果单词 XXX 的末字母与单词 YYY 的首字母相同,则 XXX 与 YYY 可以相连成 X.YX.YX.Y.(注意:XXX.YYY 之间是英文的句号 .).例如,单词 dog 与单词 ...
- 洛谷 P1498 南蛮图腾 分治递归过程详解
题目描述 自从到了南蛮之地,孔明不仅把孟获收拾的服服帖帖,而且还发现了不少少数民族的智慧,他发现少数民族的图腾往往有着一种分形的效果,在得到了酋长的传授后,孔明掌握了不少绘图技术,但唯独不会画他们的图 ...
- 洛谷 P2400 秘密文件【分治】
... 题目: 题意: 分析: 代码: 题目: 传送门 题意: 给出一个较长的字符串,要求我们按照规则进行化简,使得其长度最短 分析: 直接使用分治的思想,对于区间l−rl-rl−r,我们枚举一个分界 ...
- 洛谷P3384 - 树链剖分(树链剖分模板题)
题目链接 https://www.luogu.org/problemnew/show/P3384 [描述] 树链剖分模板题,记一下板子 #include<bits/stdc++.h> #d ...
- [WC2005]双面棋盘,洛谷P4121,线段树分治+可撤销并查集
正题 这题主要是来练手的,因为没写过可撤销的并查集,大概就是把每一个格子看成一个点,然后格子直接的边有很多的出现区间,把这些出现区间和对应的颜色打到线段树上,然后用可撤销的并查集来维护就可以了. #i ...
- 【洛谷习题】南蛮图腾
题目链接:https://www.luogu.org/problemnew/show/P1498 不好实现... 这道题在洛谷的分类是分治,我用的方法就是分治,不过却刷新的我对分治的认识.以前见过的分 ...
最新文章
- Monkey测试1——Monkey的使用
- css技巧之如何实现ul li边框重合
- 访问DBGRIDEH中的行与列
- memcached+magent实现memcached集群
- boost的chrono模块时间间隔的测试程序
- linux环境下安装gcc
- 微课|中学生可以这样学Python(8.4节):递归算法例题讲解3
- 古玩新仿品收藏若干年后有价值吗?
- POJ 1151 线段树+扫描线
- UVA11577 Letter Frequency【文本】
- tkinter label_tkinter版自制王者荣耀抽卡程序
- sqlsever	创建一个通用分页查询
- [C语言学习]C语言程序设计基础(一)
- Ubuntu14下安装使用SVN RabbitVCS客户端
- 乔家大院的5A牌子被摘了,但且别急着叫好
- 用Python批量缩放图片
- 谈一谈Coders Programmer Developer的区别
- MLCC电容和电介质材料类别X5R,X7R,Y5V,COG等一些资料
- php ajax 实现三级省市区联动
- 【Linux】Samba服务器超详细安装、配置(附带各种问题解决方式)