题目: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. Python Streaming实战2: Join的实现与数据过滤

    Hadoop Join 与 Not In的实现  (一)源数据与要实现的查询 1. 要实现的查询 select a.sid ,a.name ,b.course ,b.score from Studen ...

  2. python中偏函数

    当一个函数有很多参数时,调用者就需要提供多个参数.如果减少参数个数,就可以简化调用者的负担. 比如,int()函数可以把字符串转换为整数,当仅传入字符串时,int()函数默认按十进制转换: >& ...

  3. 全志H3-NanoPi开发板SDK之三编译流程【转】

    本文转载自:https://blog.csdn.net/yuesichiu/article/details/77600124 版权声明:本文为博主(宽简厚重,Yuesichiu)原创文章,未经博主允许 ...

  4. K8s API

    https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.10/#daemonset-v1-apps http://docs.k ...

  5. 0x5C 计数类DP

    cf 559C 考虑到黑色的格子很少,那么我把(1,1)变成黑色,然后按每个黑色格子接近终点的程度排序,计算黑色格子不经过另一个黑色格子到达终点的方案,对于当前的格子,要减去在它右下角的所有方案数(注 ...

  6. CentOS 7防火墙设置开放80端口

    在CentOS 6.x版本中,默认使用的是iptables防火墙.到了CentOS 7.x版本,默认防火墙变成了firewalld.本篇通过使用firewalld开启.关闭 HTTP(80)端口,来讲 ...

  7. 去除带有iframe页面中的2个滚动条[转]

    方法一:加载frame时修改高度 <div>    <iframe id="frame_content" name="frame_content&quo ...

  8. 【P2514】工厂选址(贪心)

    看到题了不首先应该看看数据范围确定一下算法么,这个题的数据范围大约可以支持到O(nmlogm),所以肯定不是搜索什么的,DP貌似至少也要n^2m,所以可以想一些其他的.对于题目的输入,我们发现这些输入 ...

  9. Java -- JDBC 获取数据库自动 生成的主键值

    public class Demo4 { /* create table test1 ( id int primary key auto_increment, name varchar(20) ); ...

  10. centos6.5 安装JDK

    今天在自己的centos机子上安装jdk,发现以前的教程都比较旧了,很多东西都过时了.今天把自己安装的感受写一下. 判断是否安装 首先,我们得判断机子上是不是安装了jdk,好多人推荐使用java -v ...