题目:http://uoj.ac/problem/55

https://www.luogu.org/problemnew/show/P3920

参考博客:https://www.cnblogs.com/Khada-Jhin/p/10078584.html

于是写了替罪羊树,但无论怎么调参都会T,UOJ上是80分。

别忘记给 vis 赋值!!!

更新答案和更新点分树一起做会错?总之分开写了;

注意空间。

代码如下:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#define pb push_back
using namespace std;
typedef long long ll;
int rd()
{
int ret=,f=; char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=; ch=getchar();}
while(ch>=''&&ch<='')ret=ret*+ch-'',ch=getchar();
return f?ret:-ret;
}
int Max(int x,int y){return x>y?x:y;}
int const xn=1e5+,inf=1e9,xm=;
int n,hd[xn],ct,to[xn<<],nxt[xn<<],r[xn],fa[xn],dep[xn],f[xn][];
int tot,rt[xn],frt[xn],siz[xn*xm],ls[xn*xm],rs[xn*xm];//
int size[xn],root,mx,sta[xn*xm],top;//sta
int v[xn*xm],d[xn];//v
ll ans;
vector<int>pt[xn];
bool vis[xn];
void add(int x,int y){to[++ct]=y; nxt[ct]=hd[x]; hd[x]=ct;}
int lca(int x,int y)
{
if(dep[x]<dep[y])swap(x,y);
for(int i=;i>=;i--)
if(dep[f[x][i]]>=dep[y])x=f[x][i];
for(int i=;i>=;i--)
if(f[x][i]!=f[y][i])x=f[x][i],y=f[y][i];
if(x==y)return x; return f[x][];
}
int dist(int x,int y){return d[x]+d[y]-*d[lca(x,y)];}
int node(){if(top)return sta[top--]; return ++tot;}
int *flag,tmp[xn*xm],tp;//flag
void dfsx(int x)
{
if(!x)return;
dfsx(ls[x]); tmp[++tp]=x; dfsx(rs[x]);
}
void solve(int &x,int l,int r)
{
if(l>r){x=; return;}
int mid=((l+r)>>); x=tmp[mid];
if(l==r){ls[x]=rs[x]=; siz[x]=; return;}
solve(ls[x],l,mid-); solve(rs[x],mid+,r);
siz[x]=siz[ls[x]]+siz[rs[x]]+;
}
void rebuild(int &x)
{
tp=; dfsx(x);
solve(x,,tp);
}
void ins(int &x,int val)
{
if(!x){x=node(); v[x]=val; siz[x]=; return;}
siz[x]++;
if(val<=v[x])ins(ls[x],val);
else ins(rs[x],val);
if(siz[x]*<=Max(siz[ls[x]],siz[rs[x]])*)flag=&x;//
}
void insert(int &x,int val)
{
flag=; ins(x,val);
if(flag)rebuild(*flag);//
}
void del(int &x)
{
if(!x)return;
del(ls[x]); del(rs[x]);
siz[x]=v[x]=; sta[++top]=x; x=;
}
void getrt(int x,int ff,int sum)
{
int nmx=; size[x]=;
for(int i=hd[x],u;i;i=nxt[i])
{
if(vis[u=to[i]]||u==ff)continue;
getrt(u,x,sum); size[x]+=size[u];
nmx=Max(nmx,size[u]);
}
nmx=Max(nmx,sum-size[x]);
if(mx>nmx)mx=nmx,root=x;
}
void dfs(int x,int ff)
{
size[x]=; pt[root].pb(x);
insert(rt[root],r[x]-dist(x,root));
if(fa[root])insert(frt[root],r[x]-dist(x,fa[root]));
for(int i=hd[x],u;i;i=nxt[i])
if(!vis[u=to[i]]&&u!=ff)dfs(u,x),size[x]+=size[u];
}
void build(int x,int ff,int sum)
{
vis[x]=;
del(rt[x]); del(frt[x]);
fa[x]=ff; pt[x].clear();//
dfs(x,);
for(int i=hd[x],u;i;i=nxt[i])
{
if(vis[u=to[i]])continue;
//int ns=(size[u]>size[x]?sum-size[x]:size[u]);
int ns=size[u];
mx=inf; getrt(u,,ns); build(root,x,ns);
}
}
int find(int x,int val)
{
if(!x)return ;
if(val<=v[x])return siz[x]-siz[ls[x]]+find(ls[x],val);
else return find(rs[x],val);
}
/*
void work(int x)
{
int fl=0;
rt[x]=node(); v[rt[x]]=r[x]; vis[x]=1;//
for(int y=x;y;y=fa[y])
{
size[y]++; pt[y].pb(x);
ll ds=dist(x,y),ds2;
ans+=find(rt[y],ds-r[x]);
if(fa[y])ans-=find(frt[y],(ds2=dist(x,fa[y]))-r[x]);
if(fa[y]==y)exit(0);//--------
insert(rt[y],r[x]-ds);
if(fa[y])insert(frt[y],r[x]-ds2);
if(fa[y]&&size[y]*10>(size[fa[y]]+1)*9)fl=fa[y];
}
if(fl)
{
for(int i=0;i<pt[fl].size();i++)vis[pt[fl][i]]=0;
mx=inf; getrt(fl,0,size[fl]); build(root,fa[fl],size[fl]);
}
}
*/
ll query(int x)
{
ll ret=;
for(int y=x;y;y=fa[y])ret+=find(rt[y],dist(x,y)-r[x]);
for(int y=x;fa[y];y=fa[y])ret-=find(frt[y],dist(x,fa[y])-r[x]);
return ret;
}
void work(int x)
{
int fl=-;
for(int y=x;y;y=fa[y])
{
size[y]++; pt[y].pb(x);
insert(rt[y],r[x]-dist(x,y));
if(fa[y])insert(frt[y],r[x]-dist(x,fa[y]));
if(fa[y]&&size[y]*>(size[fa[y]]+)*)fl=fa[y];//
}
if(fl!=-)
{
for(int i=;i<pt[fl].size();i++)vis[pt[fl][i]]=;
int sum=size[fl];//
mx=inf; getrt(fl,,sum); build(root,fa[fl],sum);
}
}
void init(int x,int ff,int w)
{
f[x][]=ff; d[x]=d[ff]+w; dep[x]=dep[ff]+; vis[x]=;//vis!!!
for(int i=;i<&&f[f[x][i-]][i-];i++)f[x][i]=f[f[x][i-]][i-];
}
int gt[],gtp;
void wr(ll x)
{
if(!x){puts(""); return;}
if(x<)putchar('-'),x=-x; gtp=;
while(x)gt[++gtp]=x%,x/=;
for(int i=gtp;i;i--)putchar(gt[i]+'');
puts("");
}
int main()
{
int T=rd(); n=rd(); ll lst=;
rd(); rd(); r[]=rd(); vis[]=; size[]=; dep[]=;//
insert(rt[],r[]); pt[].pb(); puts("");
for(int i=,x,w;i<=n;i++)
{
x=(rd()^(lst%inf)); w=rd(); r[i]=rd();
add(x,i); add(i,x);
init(i,x,w); fa[i]=x; //work(i);
ans+=query(i);
//printf("%lld\n",lst=ans);
wr(lst=ans);
work(i);
}
return ;
}

UOJ #55 & 洛谷 P3920 紫荆花之恋 —— 动态点分治+替罪羊树的更多相关文章

  1. luoguP3920 [WC2014]紫荆花之恋 动态点分治 + 替罪羊树

    意外的好写..... 考虑点分 \(dis(i, j) \leq r_i + r_j\) 对于过分治中心一点\(u\),有 \(dis(i, u) - r_i = dis(j, u) + r_j\) ...

  2. BZOJ3435[Wc2014]紫荆花之恋——动态点分治(替罪羊式点分树套替罪羊树)

    题目描述 强强和萌萌是一对好朋友.有一天他们在外面闲逛,突然看到前方有一棵紫荆树.这已经是紫荆花飞舞的季节了,无数的花瓣以肉眼可见的速度从紫荆树上长了出来.仔细看看的话,这个大树实际上是一个带权树.每 ...

  3. [WC2014]紫荆花之恋(动态点分治+替罪羊思想)

    题目描述 强强和萌萌是一对好朋友.有一天他们在外面闲逛,突然看到前方有一棵紫荆树.这已经是紫荆花飞舞的季节了,无数的花瓣以肉眼可见的速度从紫荆树上长了出来.仔细看看的话,这个大树实际上是一个带权树.每 ...

  4. uoj 55 紫荆花之恋 动态点分治+替罪羊式重构+treap

    每插入一个点,直接把它当做重心插入原树,当做是动态点分树一样维护 但这样深度会越来越大,所以我们用类似替罪羊的方法 当树失去平衡时,对子树进行一次点分,保证复杂度 #include <cstdi ...

  5. 洛谷 P6199 - [EER1]河童重工(点分治+虚树)

    洛谷题面传送门 神仙题. 首先看到这样两棵树的题目,我们肯定会往动态树分治的方向考虑.考虑每次找出 \(T_2\) 的重心进行点分治.然后考虑跨过分治中心的点对之间的连边情况.由于连边边权与两棵树都有 ...

  6. UOJ 55 【WC2014】紫荆花之恋——点分治+平衡树

    题目:http://uoj.ac/problem/55 点分治.在点分树上每个点上用 splay 维护管辖的点的情况.做几次就重构点分树.TLE.只能过 20 分. #include<cstdi ...

  7. UOJ#55. 【WC2014】紫荆花之恋 点分树 替罪羊树 平衡树 splay Treap

    原文链接https://www.cnblogs.com/zhouzhendong/p/UOJ55.html 题解 做法还是挺容易想到的. 但是写的话…… 首先这种题如果只要求一棵树中的满足条件的点数( ...

  8. UOJ#55. 【WC2014】紫荆花之恋

    传送门 暴力思路就是每次点分治计算答案 点分治之后,条件可以变成 \(dis_i-r_i\le r_j-dis_j\) 每次只要查找 \(r_j-dis_j\) 的排名然后插入 \(dis_j-r_j ...

  9. 洛谷P3120 [USACO15FEB]牛跳房子(动态开节点线段树)

    题意 题目链接 Sol \(f[i][j]\)表示前\(i\)行\(j\)列的贡献,转移的时候枚举从哪里转移而来,复杂度\(O(n^4)\) 然后考虑每一行的贡献,动态开节点线段树维护一下每种颜色的答 ...

随机推荐

  1. eclipse新建自定义EL函数

    ==================================================================================================== ...

  2. comet4j开发指南

    http://blog.csdn.net/majian_1987/article/details/8489738 好多朋友反映,因排版问题,文章部分边缘内容无法查看.尝试过排版,但仍无法显示正常,所以 ...

  3. linux 音频驱动

    转:https://wenku.baidu.com/view/7394e16d7e21af45b307a8dc.html?pn=51 linux_sound_alsa_ALSA体系SOC子系统中数据流 ...

  4. shell复制除了某个文件的操作

    将app的已经写成带有日期名的日志放到归档特定目录(刨除正在记录的日志) find $APPHOME/logs | grep -v "info.log\|debug.log\|error.l ...

  5. 常用 GDB 命令中文速览

    转自:https://linux.cn/article-8900-1.html?utm_source=index&utm_medium=moremore 目录 break -- 在指定的行或函 ...

  6. Django 模板标签[转]

    Django 模板标签if/else 标签 基本语法格式如下: {% if condition %}     ... display{% endif %} 或者: {% if condition1 % ...

  7. <转载>获取运行中的TeamViewer的账号和密码

    #define WIN32_LEAN_AND_MEAN #include <windows.h> #include <iostream> #pragma comment( li ...

  8. vc 自删除

    // delself.cpp : 定义控制台应用程序的入口点.// #include "stdafx.h"#include <windows.h>#include &l ...

  9. Rem是什么,牛逼的Vue,Epub竟然可以实现阅读器功能。太牛了。

    rem 相当于根元素font-size值的倍数. 1rem=根元素font-size 2rem=根元素font-size * 2 // 1rem = fontSize px // 1px = (1/f ...

  10. AppStore审核2.1被拒大礼包过审经历

    本团队的iOS端迭代至今,经历过AppStore审核的数次调整,包括审核时长.严厉程度等,尝过各种花式的拒绝理由,但从没有像2018年初这次来得猛烈和漫长.从首次提交到最后过审几乎花费一个月的时间,下 ...