【WC2014】紫荆花之恋【替罪羊思想】【动态点分树】【替罪羊树】

传送门

题意:有一棵开始时没有结点的树,nnn次询问,每次新加一点并给定父结点、到父亲的距离、参数rir_iri,并询问满足dist(u,v)≤ru+rvdist(u,v)\leq r_u+r_vdist(u,v)ru+rv的点对(u,v)(u,v)(u,v)的对数。

n≤105n\leq 10^5n105,强制在线

很好的一道题,并没有江湖上传言的那么恐怖我只写了两天而已

显然我们只需要考虑新加的点的贡献和之前加起来即可

设当前加的点为uuu

盯着这个式子:

dist(u,v)≤ru+rvdist(u,v)\leq r_u+r_vdist(u,v)ru+rv

如果我们随便找到uuuvvv路径上的一点ppp ,可以拆成

dist(u,p)+dist(v,p)≤ru+rvdist(u,p)+dist(v,p)\leq r_u+r_vdist(u,p)+dist(v,p)ru+rv

我们要求的就是满足

dist(v,p)−rv≤ru−dist(u,p)dist(v,p)-r_v\leq r_u-dist(u,p)dist(v,p)rvrudist(u,p)

vvv的个数

如果ppp固定,就可以用平衡树瞎维护一下

然后可以枚举uuu的祖先作为ppp统计答案

但显然给条链就挂了

注意到我们这样做的复杂度是O(u的深度)O(u的深度)O(u),可以试试点分树

如果树的形态是固定的,因为点分树的性质

点分树上两点的lcalcalca在原树上这两点的路径上

并且我们上面要求的恰好只是在路径上,所以可以在点分树上用相同的方式统计

具体实现的时候,每个点分树上的结点uuu开棵平衡树记录子树中所有点vvvdist(v,u)−rvdist(v,u)-r_vdist(v,u)rv

然后设新加的点为xxx,从xxx开始往上跳,跳到uuu时询问uuu的平衡树中≤rx−dist(x,u)\leq r_x-dist(x,u)rxdist(x,u)的点的个数

但这样会算进不是简单路径的,所以需要记录uuu的 某个儿子 的子树 中的结点vvvdist(v,u)−rvdist(v,u)-r_vdist(v,u)rv的信息减一下

具体而言就是每个结点uuu再开一个平衡树记录子树中的每个结点vvvdist(v,fau)−rvdist(v,fa_u)-r_vdist(v,fau)rv

但是这棵树还会动

采用黑科技,用替罪羊树的思想,在跳点分树的时候如果有偏得太严重的点,就把整个子树重构

说着简单其实细节不少

因为常数大得惊人,所以内部平衡树用了替罪羊树

真·奥义·替罪羊套替罪羊

复杂度O(能过)O(能过)O()

本题的易错细节:

  1. 内部替罪羊重构的时候要清空chchch数组
  2. 点分树重构子树的时候在原树上只是一个连通块,需要dfs一遍打个标记,后面只访问有标记的点
  3. 点分树重构子树时要清空所有结点的一堆信息
  4. 因为要算distdistdist,在点分树重构前要先把新的子树的根(即整个连通块的重心)的父亲接上
  5. 要记录点分树上每个点是父亲的第几个儿子并传引用
  6. 在点分树重构时暴力建平衡树要开两个vector并分别排序
  7. 点分树重构不能修改up,disup,disup,dis等信息
  8. 判断重构时要特判是整个点分树的根的情况
  9. 要写内存回收池
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cctype>
#include <vector>
#include <algorithm>
#include <cassert>
#define MAXN 100005
#define MAXM 200005
using namespace std;
const int MOD=1e9;
const double alpha=0.8;
typedef long long ll;
struct edge{int u,v,w;}e[MAXM];
int head[MAXN],nxt[MAXM],cnt;
inline void addnode(int u,int v,int w)
{e[++cnt]=(edge){u,v,w};nxt[cnt]=head[u];head[u]=cnt;
}
inline int read()
{int ans=0;char c=getchar();while (!isdigit(c)) c=getchar();while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();return ans;
}
int dis[MAXN],dep[MAXN],up[MAXN][20];
inline int lca(int x,int y)
{if (dep[x]<dep[y]) swap(x,y);int t=dep[x]-dep[y];for (int i=0;(1<<i)<=t;i++) if (t&(1<<i)) x=up[x][i];if (x==y) return x;for (int i=19;i>=0;i--)	if (up[x][i]!=up[y][i]) x=up[x][i],y=up[y][i];return up[x][0];
}
inline int dist(const int& x,const int& y){return dis[x]+dis[y]-2*dis[lca(x,y)];}
namespace SGT
{int *pos;const int N=MAXN<<6;int bin[N],lis[N];int ch[N][2],siz[N],val[N],tot;inline int newnode(const int& v){int x=(bin[0]? bin[bin[0]--]:++tot);return ch[x][0]=ch[x][1]=0,siz[x]=1,val[x]=v,x;}inline void update(const int& x){siz[x]=siz[ch[x][0]]+1+siz[ch[x][1]];}void insert(int& x,int v){if (!x) return (void)(x=newnode(v));insert(ch[x][v>val[x]],v);update(x);if (siz[ch[x][0]]>siz[x]*alpha||siz[ch[x][1]]>siz[x]*alpha) pos=&x;}void build(int& x,int l=1,int r=lis[0]){if (l>r) return (void)(x=0);int mid=(l+r)>>1;x=newnode(lis[mid]),build(ch[x][0],l,mid-1),build(ch[x][1],mid+1,r),update(x);}void dfs(int& x){if (!x) return;dfs(ch[x][0]);bin[++bin[0]]=x,lis[++lis[0]]=val[x];dfs(ch[x][1]);x=0;}inline void rebuild(){if (pos==NULL) return;lis[0]=0,dfs(*pos),build(*pos),pos=NULL;}inline void modify(int& x,int v){insert(x,v),rebuild();}int query(int x,int v){if (!x) return 0;if (v<val[x]) return query(ch[x][0],v);return siz[ch[x][0]]+1+query(ch[x][1],v);}inline void getbuf(const vector<int>& v){lis[0]=0;for (int i=0;i<(int)v.size();i++) lis[++lis[0]]=v[i];}
}
using SGT::modify;
using SGT::query;
using SGT::getbuf;
int fa[MAXN],idx[MAXN],rt[MAXN],prt[MAXN],r[MAXN],*pos;
int Rt=1;
vector<int> son[MAXN],sub[MAXN];
inline void addnode(int u,int f){fa[u]=f,son[f].push_back(u),idx[u]=son[f].size()-1;}
inline int insert(int x)
{int ans=0;for (int u=x,v=0;u;v=u,u=fa[u]){int val=r[x]-dist(x,u);ans+=query(rt[u],val)-query(prt[v],val);modify(rt[u],-val);if (v) modify(prt[v],-val);if (SGT::siz[rt[v]]>SGT::siz[rt[u]]*alpha) pos=(fa[u]? &son[fa[u]][idx[u]]:&Rt);}return ans;
}
bool vis[MAXN];
vector<int> block;
void dfs(int u){vis[u]=1,block.push_back(u);for (int i=0;i<(int)son[u].size();i++) dfs(son[u][i]);}
int siz[MAXN],maxp[MAXN]={0x7fffffff},root;
void findrt(int u,int f,int sum)
{siz[u]=1,maxp[u]=0;for (int i=head[u];i;i=nxt[i])if (vis[e[i].v]&&e[i].v!=f){findrt(e[i].v,u,sum);siz[u]+=siz[e[i].v],maxp[u]=max(maxp[u],siz[e[i].v]);}if (sum-siz[u]>maxp[u]) maxp[u]=sum-siz[u];if (maxp[u]<maxp[root]) root=u;
}
int getsiz(int u,int f)
{int ans=1;for (int i=head[u];i;i=nxt[i])if (vis[e[i].v]&&e[i].v!=f)ans+=getsiz(e[i].v,u);return ans;
}
void build()
{vis[root]=0;int u=root;sub[u].push_back(u);for (int i=head[u];i;i=nxt[i])if (vis[e[i].v]){root=0;findrt(e[i].v,0,getsiz(e[i].v,0));int v=root;addnode(v,u);build();for (vector<int>::iterator it=sub[v].begin();it!=sub[v].end();++it) sub[u].push_back(*it);}vector<int> tmp1,tmp2;for (int i=0;i<(int)sub[u].size();i++){int v=sub[u][i];tmp1.push_back(dist(v,u)-r[v]);tmp2.push_back(dist(v,fa[u])-r[v]);}sort(tmp1.begin(),tmp1.end());getbuf(tmp1),SGT::build(rt[u]);if (fa[u]){sort(tmp2.begin(),tmp2.end());getbuf(tmp2),SGT::build(prt[u]);}
}
int main()
{read();int n=read();ll lans=0;for (int u=1;u<=n;u++){int a,c;a=read()^(lans%MOD),c=read(),r[u]=read();up[u][0]=a;for (int i=1;i<20;i++) up[u][i]=up[up[u][i-1]][i-1];dis[u]=dis[up[u][0]]+c,dep[u]=dep[up[u][0]]+1;if (u>1) addnode(u,a);addnode(u,a,c),addnode(a,u,c);printf("%lld\n",lans+=insert(u));if (pos==NULL) continue;
//		cerr<<"rebuild "<<*pos<<'\n';int f=fa[*pos],id=idx[*pos];dfs(*pos),root=0,findrt(*pos,0,SGT::siz[rt[*pos]]);int RT=root;
//		cerr<<*pos<<' '<<RT<<'\n';for (int i=0;i<(int)block.size();i++) {int v=block[i];SGT::dfs(rt[v]),SGT::dfs(prt[v]);fa[v]=idx[v]=rt[v]=prt[v]=0;son[v].clear(),sub[v].clear();}fa[RT]=f,idx[RT]=id,*pos=RT;build();block.clear();pos=NULL;} return 0;
}

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

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

相关文章

NuGet是什么?理解与使用

如果你了解python&#xff0c;那么它类似pip。如果你了解nodejs&#xff0c;那么它类似npm。如果你了解ruby&#xff0c;那么它类似gem。对&#xff0c;它就是一个包&#xff08;package&#xff09;管理平台&#xff0c;确切的说是 .net平台的包管理工具&#xff0c;它提供了一…

P2468 [SDOI2010]粟粟的书架 主席树 + 二分 + 二维前缀和

传送门 文章目录题意&#xff1a;题意&#xff1a;题意&#xff1a; 给你一个n∗mn*mn∗m的矩阵&#xff0c;每次询问一个矩形&#xff0c;左上角是(x1,y1)(x_1,y_1)(x1​,y1​)&#xff0c;右上角是(x2,y2)(x_2,y_2)(x2​,y2​)&#xff0c;和一个hhh&#xff0c;问是否能选出…

带花树学习笔记

引入 带花树解决的是一般图的最大匹配问题。 学习此算法前你需要掌握二分图匹配的匈牙利算法&#xff0c;至少需要知道它的思想。 理论 众所周知&#xff0c;二分图匹配的思想是不断地找增广路。 严谨地讲&#xff0c;是找到了一条简单路径&#xff0c;它的起点和终点都未…

你竟然没用 Nuget 构建项目?

想写这篇文章缘起于公众号文章里的一条留言&#xff1a;对于一个现代化的开发平台&#xff0c;建立一种让开发者创建&#xff0c;分享与使用可复用代码的机制是十分必要的。这种“可复用代码”被打包后的文件通常被称作“包”&#xff08;package&#xff09;&#xff0c;对于.…

Codeforces Round #339 (Div. 1) D. Kingdom and its Cities 虚树 + dp

传送门 文章目录题意&#xff1a;思路&#xff1a;题意&#xff1a; n≤1e5,∑k≤1e5,q≤1e5n\le1e5,\sum k\le1e5,q\le1e5n≤1e5,∑k≤1e5,q≤1e5。 思路&#xff1a; 经过分析&#xff0c;外敌占领的城市只有可能是两点的lcalcalca或者两点之间任意一点&#xff0c;是哪个点…

小白开学Asp.Net Core《四》 —— 使用AspectCore-Framework

小白开学Asp.Net Core《四》—— 使用AspectCore-Framework一、AspectCore-Framework说AspectCore-Framework不得不先谈谈的AOP&#xff0c;AOP&#xff1a;在软件业&#xff0c;AOP为Aspect Oriented Programming的缩写&#xff0c;意为&#xff1a;面向切面编程&#xff0c;通…

【WC2016】挑战NPC 【带花树】【建图】

传送门 题意&#xff1a;有nnn个球和mmm个筐&#xff0c;每个筐最多放333个球&#xff0c;每个球只能放入特定的一些筐中&#xff0c;在题中给出。构造一种放球的方案使得nnn个球都被放在某个筐中且 球的个数不超过111 的筐的数量尽量大。 m≤100,n≤3mm\leq 100,n\leq 3mm≤1…

P4103 [HEOI2014]大工程 虚树 + dp

传送门 文章目录题意&#xff1a;思路&#xff1a;题意&#xff1a; 思路&#xff1a; 简化一下题意就是求树上给定点集中每两个点之间的距离之和&#xff0c;相距最远的点&#xff0c;相距最近的点。 对于距离和我们统计一下边的贡献就好啦&#xff0c;边两头的sizesizesize乘…

【翻译】Keras.NET简介 - 高级神经网络API in C#

用C#&#xff0c;远离996Keras.NETKeras.NET是一个高级神经网络API&#xff0c;它使用C#编写&#xff0c;并带有Python绑定&#xff0c;可以在Tensorflow、CNTK或Theano上运行。其关注点是实现快速实验。因为做好研究的关键是&#xff1a;能在尽可能短的时间内从一个想法发展出…

TIOBE 6月排行:C# 以微弱的优势超过了 Visual Basic .NET 的排名,再次进入 TOP 5

月经贴警告……TIOBE 编程语言排行榜 7 月更新已公布&#xff0c;排名前十的分别是&#xff1a;Java, C, Python, C, C#, Visual Basic .NET, JavaScript, PHP, SQL 和汇编语言。和上个月的不同之处主要是 C# 以微弱的优势超过了 Visual Basic .NET 的排名&#xff0c;再次进入…

ETT学习笔记

ETT&#xff08;Eular Tour Tree&#xff09;是一种维护有根树的数据结构&#xff0c;支持以下操作 修改一个点的点权子树修改单点查询点到根路径查询修改一个点的父亲 据说可以支持换根&#xff0c;但用的不多而且据说很难写&#xff0c;所以似乎失传了&#xff08; 其实没…

Codeforces Round #635 (Div. 2) D. Xenia and Colorful Gems 暴力 + 二分

传送门 文章目录题意&#xff1a;思路&#xff1a;题意&#xff1a; 给你三个数组a,b,ca,b,ca,b,c&#xff0c;让你从每个数组中选择一个数x,y,zx,y,zx,y,z&#xff0c;使得(x−y)2(x−z)2(y−z)2(x-y)^2(x-z)^2(y-z)^2(x−y)2(x−z)2(y−z)2最小&#xff0c;求这个最小值。 …

用.NET Core实现一个类似于饿了吗的简易拆红包功能

需求说明以前很讨厌点外卖的我&#xff0c;最近中午经常点外卖&#xff0c;因为确实很方便&#xff0c;提前点好餐&#xff0c;算准时间&#xff0c;就可以在下班的时候吃上饭&#xff0c;然后省下的那些时间就可以在中午的时候多休息一下了。点餐结束后&#xff0c;会有一个好…

【POI2011】LIZ-Lollipop 【构造】

传送门 题意&#xff1a;给一个长度为nnn的只有111和222的序列&#xff0c;多次询问给定xxx构造或判断无法构造一个区间和为xxx 注意到111和222实质上是改不改变奇偶性&#xff0c;所以往这上面考虑 我们发现如果一个区间[L,R][L,R][L,R]和为x(x>2)x(x>2)x(x>2),我…

kubernetes实战篇之helm示例yaml文件文件详细介绍

前面完整示例里,我们主要讲解helm打包,部署,升级,回退等功能,关于这里面的文件只是简单介绍,这一节我们详细介绍一下这里面的文件,以方便我们参照创建自己的helm chart.Helm Chart 结构Chart 目录结构mychart/ Chart.yaml LICENSE README.md values.yaml requirements.yam…

P4309 [TJOI2013]最长上升子序列 平衡树 + dp

传送门 文章目录题意&#xff1a;思路&#xff1a;题意&#xff1a; 思路&#xff1a; 注意到一个很关键的条件&#xff0c;每次插入iii&#xff0c;而iii是递增的&#xff0c;也就是说插入iii之后只会从前面的最大值转移过来&#xff0c;所以我们现在只需要维护插入操作即可&…

【AGC035C】Skolem XOR Tree【异或】【构造】

传送门 题意&#xff1a;给定nnn&#xff0c;构造或判断无法构造一个2n2n2n个结点的树&#xff0c;其中结点iii和ininin的权值为iii,且所有iii和ininin路径权值异或和等于iii。 注意到 2i⊕2i112i\oplus2i112i⊕2i11&#xff0c;然后可以脑补出 然而111没处理 发现1⊕2⊕301\…

ASP.NET Core 管道再探

几乎任何服务器端处理环境都有自己的直通组件管道&#xff0c;用于检查、重路由或修改传入请求和传出响应。经典 ASP.NET 围绕 HTTP 模块理念进行排列&#xff0c;而 ASP.NET Core 采用基于中间件组件的更现代的体系结构。最终目的是相同的 - 允许可配置的外部模块以请求&#…

GRPC与.net core

QQ讨论群&#xff1a;953553560正文系列章节GRPC与.net coreGRPC截止时间与元数据GRPC与netcore IdentityGRPC与netcore IdentityServer4概述GRPC的数据交互模式有&#xff1a;1.单项RPC&#xff0c;最简单的数据交换方式&#xff0c;客户端发出单个请求&#xff0c;收到单个响…

【Hitachi2020C】ThREE【构造】【二分图染色】

传送门 题意&#xff1a;给一棵nnn个结点的树&#xff0c;构造一个nnn阶排列ppp&#xff0c;使得所有距离为333的点对(i,j)(i,j)(i,j)满足pipjp_ip_jpi​pj​和pipjp_ip_jpi​pj​至少一个为333的倍数。 分析一下&#xff0c;这个条件等价于所有距离333的点对点权对三取模后不…