P3920 WC2014 紫荆花之恋
P3920 WC2014 紫荆花之恋
毒瘤题目,动态点分树。
前置科技点
- 替罪羊树
- 高速平衡树(除去
fhq_treap
和splay
之外的所有平衡树)
约定
\(dis(u,v)\) 为原树上 \(u,v\) 两点间的距离
\(siz\) 为子树大小
思路
维护一棵可以动态插入节点的点分树,有点权和边权,求任意两点点权和大于两点间路径边权和的节点对数。
强制在线(万恶之源)
part1:处理询问
如果把强制在线去掉,建点分树,这题是一个很经典的点分树可以维护的问题。
在点分树上某个节点 \(i\) 统计所有经过这个点连接的点对的个数:
\]
移项得:
\]
枚举 \(u\),沿着 \(u\) 在点分树上祖先,统计满足要求的 \(v\) 即可。
用平衡树维护,可以做到 \(O(\log n)\) 查询。
这里我们需要处理去重的问题,有哪些 \((u,v)\) 会在点分树上的父亲处再次统计一次。
设 \(i\) 的点分树上父亲为 \(f\),我们需要把自己子树内的节点在父亲平衡树内储存的信息 copy 一份到 \(i\),减去满足 \(-(dis(f,u)-r_u)\geq dis(v,f)-r_v\) 的点对数列。
这样下来,查询时间复杂度 \(\log^2 n\)。
part2:替罪羊树维护点分树
替罪羊树的思想使得替罪羊树保证了高度在 \(\log\) 以内的思想,我们用类似的思想维护点分树。
每次直接把节点接在父亲上,然后沿着点分树上的祖先检查是否有儿子节点的 \(siz*a\) 大于父亲节节点的 \(siz*b\),直到找到最浅的一个满足这样关系的点,对其所在子树进行重构。
重构时,重置一些数组:
1.该子树内所有平衡树。
2.已加入点分树的标记。
3.点分树上所在子树的编号集数组。
4.点分树上的祖先数组(这个数组只需要清空连续的一部分,可以利用加入点分树的标记清空)。
Ps:按照笔者的习惯,祖先数组包括节点本身。
part3:点分树
最主要的过程竟然是最简单的。
构建点分树,点分树上的节点 \(u\)。
维护两个平衡树,设 \(u\) 的父亲为 \(f\),\(v\) 为 \(u\) 的点分树上子树内的一个节点,第一个平衡树加入 \(dis(u,v)-r_v\) 第二个维护 \(dis(f,v)-r_v\),供后面的求值操作使用。
维护已加入点分树标记。
维护祖先数组(这里的祖先数组使用
pair
,first
维护祖先标号,second
维护距离)。维护点分树上子树集数组。
part4:插入节点
插入一个节点 \(u\),把他挂在他的父亲 \(f\) 上。
1.链式前向星加边。
2.将 \(f\) 的祖先数组复制下来,将 \(second\) 全部加上边权 \(w\),最后加入自己。
3.更新祖先的点分树上子树集数组。
4.沿着祖先数组,更新两颗平衡树。
5.从最浅的祖先开始查找不合符要求的 \(siz\),并对此节点的点分树子树进行重构。
节点 1 的插入需要特判。
关于平衡树
本题需要高速平衡树,但是我们可以用 pb_ds
库中的平衡树来代替,可以使用 pair
插入的方法消除不可以重复值的限制(第一位存值,第二位随机一个数)。
实测,替罪羊树 \(a\) 取 \(0.75\) 可以在该方法下通过此题。
代码
#include<bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std;
using namespace __gnu_pbds;
#define ll long long
#define pil pair<int,ll>
#define pli pair<ll,int>
#define pll pair<ll,ll>
#define mod 1000000000
#define F first
#define S second
const int maxn=1e5+5;
tree<pli, null_type, less<pli>, rb_tree_tag, tree_order_statistics_node_update> T1[maxn],T2[maxn];
int r[maxn];
struct Edge//链式前向星存边
{
int tot;
int head[maxn];
struct edgenode{int to,nxt;ll w;}edge[maxn*2];
inline void add(int x,int y,ll z)
{
tot++;
edge[tot].to=y;
edge[tot].nxt=head[x];
edge[tot].w=z;
head[x]=tot;
}
}T;
namespace VCD_tree
{
int rt;
int siz[maxn];
bool cut[maxn],book[maxn];//cut 为加入点分树标记
vector<pil>fa[maxn];//祖先数组
vector<int>ve[maxn];//点分树子树数组
inline void dfs_siz(int u)
{
book[u]=true;siz[u]=1;
for(int i=T.head[u];i;i=T.edge[i].nxt)
{
int v=T.edge[i].to;
if(!book[v]&&!cut[v]) dfs_siz(v),siz[u]+=siz[v];
}
book[u]=false;
}
inline int dfs_rt(int u,const int tot)
{
book[u]=true;int ret=u;
for(int i=T.head[u];i;i=T.edge[i].nxt)
{
int v=T.edge[i].to;
if(!book[v]&&!cut[v]&&siz[v]*2>=tot){ret=dfs_rt(v,tot);break;}
}
book[u]=false;return ret;
}
inline void dfs2(int u,const int f,ll dis)
{
book[u]=true;
int k=fa[u].size()-1;
if(k>=0) T2[f].insert({fa[u][k].S-r[u],rand()});T1[f].insert({dis-r[u],rand()});
fa[u].push_back({f,dis});ve[f].push_back(u);
for(int i=T.head[u];i;i=T.edge[i].nxt)
{
int v=T.edge[i].to;
if(!book[v]&&!cut[v]) dfs2(v,f,dis+T.edge[i].w);
}
book[u]=false;
}
inline void solve(int u,int f)
{
dfs_siz(u);int g=dfs_rt(u,siz[u]);cut[g]=true;
int k=fa[g].size()-1;
if(k>=0) T2[g].insert({fa[g][k].S-r[g],rand()});T1[g].insert({-r[g],rand()});
fa[g].push_back({g,0});ve[g].push_back(g);
for(int i=T.head[g];i;i=T.edge[i].nxt)
{
int v=T.edge[i].to;
if(!cut[v]){dfs2(v,g,T.edge[i].w);solve(v,g);}
}
}//以上为点分树基操
inline void rebuild(int p)//重构前清空
{
for(auto i:ve[p])
{
if(i==p) continue;
for(auto it1=fa[i].rbegin();it1->F!=p;it1=fa[i].rbegin()) fa[i].pop_back();
ve[i].clear();T1[i].clear();T2[i].clear();fa[i].pop_back();cut[i]=false;
}
for(auto it1=fa[p].rbegin();it1->F!=p;it1=fa[p].rbegin()) fa[p].pop_back();
ve[p].clear();T1[p].clear();T2[p].clear();fa[p].pop_back();cut[p]=false;
solve(p,0);
}
inline ll insert(int u,int f,ll w)//插入节点
{
if(!f)//特判
{
fa[u].push_back({u,0});ve[u].push_back(u);
T1[u].insert({-r[u],rand()});rt=u;
return 0;
}
T.add(u,f,w),T.add(f,u,w);
for(auto i:fa[f]) fa[u].push_back({i.F,i.S+w}),ve[i.F].push_back(u);
fa[u].push_back({u,0});ve[u].push_back(u);
ll lst=1e18;
for(auto i:fa[u])//更新平衡树
{
if(lst!=1e18) T2[i.F].insert({lst,rand()});
T1[i.F].insert({i.S-r[u],rand()});lst=i.S-r[u];
}
vector<pil>::iterator it1,it2;//查是否需要重构
for(it1=fa[u].begin(),it2=it1,it2++;it2!=fa[u].end();it1++,it2++)
if(ve[it1->F].size()*3<=ve[it2->F].size()*4){rebuild(it1->F);break;}
ll res=T1[u].order_of_key({r[u]+1,-1});//求答案
int t=fa[u].size()-1;
for(int i=fa[u].size()-2;i>=0;t=i,i--)
{
res+=T1[fa[u][i].F].order_of_key({-(fa[u][i].S-r[u])+1,-1});
res-=T2[fa[u][t].F].order_of_key({-(fa[u][i].S-r[u])+1,-1});
}
return res-1;//-1是要减去自己
}
inline void init(){memset(cut,1,sizeof(cut));}//初始化
}
ll lst;
int n;
inline int read() {
int s = 0, w = 1;
char ch = getchar();
while (ch < '0' || ch > '9') {
if (ch == '-')
w = -1;
ch = getchar();
}
while (ch >= '0' && ch <= '9') s = s * 10 + ch - '0', ch = getchar();
return s * w;
}
inline void write(ll X)
{
if(X<0) {X=~(X-1); putchar('-');}
if(X>9) write(X/10);
putchar(X%10+'0');
}
int main()
{
int _;scanf("%d",&_);
scanf("%d",&n);
VCD_tree::init();
for(int i=1;i<=n;i++)
{
int f,w;
f=read(),w=read(),r[i]=read();
f^=(lst)%mod;
lst+=VCD_tree::insert(i,f,w);
write(lst);putchar('\n');
}
}
166行,2 weeks,感觉身体被掏空。
P3920 WC2014 紫荆花之恋的更多相关文章
- luogu P3920 [WC2014]紫荆花之恋
LINK:紫荆花之恋 每次动态加入一个节点 统计 有多少个节点和当前节点的距离小于他们的权值和. 显然我们不能n^2暴力. 考虑一个简化版的问题 树已经给出 每次求某个节点和其他节点的贡献. 不难想到 ...
- BZOJ 3435: [Wc2014]紫荆花之恋
二次联通门 : BZOJ 3435: [Wc2014]紫荆花之恋 二次联通门 : luogu P3920 [WC2014]紫荆花之恋 /* luogu P3920 [WC2014]紫荆花之恋 怀疑人生 ...
- bzoj 3435: [Wc2014]紫荆花之恋 替罪羊树维护点分治 && AC400
3435: [Wc2014]紫荆花之恋 Time Limit: 240 Sec Memory Limit: 512 MBSubmit: 159 Solved: 40[Submit][Status] ...
- 【BZOJ3435】[Wc2014]紫荆花之恋 替罪点分树+SBT
[BZOJ3435][Wc2014]紫荆花之恋 Description 强强和萌萌是一对好朋友.有一天他们在外面闲逛,突然看到前方有一棵紫荆树.这已经是紫荆花飞舞的季节了,无数的花瓣以肉眼可见的速度从 ...
- BZOJ3435 & 洛谷3920 & UOJ55:[WC2014]紫荆花之恋
https://www.lydsy.com/JudgeOnline/problem.php?id=3435 https://www.luogu.org/problemnew/show/P3920 ht ...
- BZOJ3435[Wc2014]紫荆花之恋——动态点分治(替罪羊式点分树套替罪羊树)
题目描述 强强和萌萌是一对好朋友.有一天他们在外面闲逛,突然看到前方有一棵紫荆树.这已经是紫荆花飞舞的季节了,无数的花瓣以肉眼可见的速度从紫荆树上长了出来.仔细看看的话,这个大树实际上是一个带权树.每 ...
- [WC2014]紫荆花之恋(动态点分治+替罪羊思想)
题目描述 强强和萌萌是一对好朋友.有一天他们在外面闲逛,突然看到前方有一棵紫荆树.这已经是紫荆花飞舞的季节了,无数的花瓣以肉眼可见的速度从紫荆树上长了出来.仔细看看的话,这个大树实际上是一个带权树.每 ...
- UOJ#55 [WC2014]紫荆花之恋
题目描述 强强和萌萌是一对好朋友.有一天他们在外面闲逛,突然看到前方有一棵紫荆树.这已经是紫荆花飞舞的季节了,无数的花瓣以肉眼可见的速度从紫荆树上长了出来. 仔细看看的话,这个大树实际上是一个带权树. ...
- 【bzoj3435】[Wc2014]紫荆花之恋 替罪点分树套SBT
题目描述 强强和萌萌是一对好朋友.有一天他们在外面闲逛,突然看到前方有一棵紫荆树.这已经是紫荆花飞舞的季节了,无数的花瓣以肉眼可见的速度从紫荆树上长了出来.仔细看看的话,这个大树实际上是一个带权树.每 ...
- BZOJ3435: [Wc2014]紫荆花之恋(替罪羊树,Treap)
Description 强强和萌萌是一对好朋友.有一天他们在外面闲逛,突然看到前方有一棵紫荆树.这已经是紫荆花飞舞的季节了,无数的花瓣以肉眼可见的速度从紫荆树上长了出来.仔细看看的话,这个大树实际上是 ...
随机推荐
- 阿里云 ACK Pod重启:pod was OOM killed
原因为:limits和requests的值设定为一样的了, pod request达到了limit限制,kubelet会统计到request+缓存就超限,然后触发自动重启 resources: lim ...
- windows server 2019 IIS网站属性上没有asp.net标签 ,aspnet_regiis -i 不能安装
在新的服务器版本已经不能通过 aspnet_regiis -i安装了,可以通过以下语句完成: dism /online /enable-feature /featurename:IIS-ASPNET4 ...
- 基于 GoFrame 框架的 Go 项目打包成镜像,并上传至 Harbor 镜像库
〇.前言 在云服务时代最流行的部署方式就是容器部署,这也是最推荐的部署方式. 对于 GoFrame 框架就不多介绍了,直接来初始化一个 demo,备用. // 初始化一个项目:gf-demo gf i ...
- 在stable diffussion中控制生成图片的光线
在摄影中,光线起着至关重要的作用,它对图像的整体质量和氛围有着显著的影响.您可以使用光线来增强主题,创造深度和维度,传达情感,以及突出重要细节. 在这篇文章中,我会告诉你如何在stable diffu ...
- CSS – Display block, inline, inline-block
前言 之前 W3Schools 学习笔记就有提到了 CSS Layout - The display Property 这篇做更多的解释. 参考: CSS Display FLEX vs Block, ...
- 应聘软件测试 HR 会问到哪些问题?收藏这一篇就够了!
1.你还有收到其他offer吗? 其实hr问你offer情况,是对你感兴趣,想要进一步了解你,看下你的市场竞争力. 但注意不要太坦诚的说:我还没有offer或者收到两个offer还想对比对比:也不要撒 ...
- 选择:Qt Creator、Qt Designer、Qt Design Studio,三种开发工具,您选择哪一种?
前言 本文介绍了三种QT开发工具的特点,以及各自的优点和缺点. QT三种工具对比 QT提供的工具 Qt Creator: 扮演的是QT Widgets和QT QML的IDE的角色. 优点: 可以编写C ...
- oneforall配置环境,报错cannot import name 'sre_parse' from 're' 解决方法
高版本python中re模块没有了sre_parse模块, 可以修改python中的exrex.py 代码,直接导入sre_parse模块
- Linux中的一些命令
1.新增新用户lili,不允许登录系统,用户ID为3000===useradd -u 3000 -s /sbin/nologin lili2.循环创建目录 /www/wwwroot/html/test ...
- 对抗生成网络(GAN)简单介绍
对抗生成网络主要由生成网络和判别网络构成,GAN在图像领域使用较多.利用生成网络生成假的图像,然后利用判别器是否能判断该图像是假的. 1.用于医学图像分割,一般我们可以利用一个U-Net网络生成分割结 ...