题目: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. imx6qsbd kpp

    转: https://blog.csdn.net/zyaiwmy/article/details/54313025 https://www.aliyun.com/jiaocheng/123973.ht ...

  2. openpyxl之excel操作

    一.读取excel中内容 1.导入模块 : from openpyxl import load_workbook 2.打开excel : workbook = load_workbook(" ...

  3. centos7环境下zookeeper的搭建步骤之单机伪集群

    首先说明:这里是单机版的伪集群搭建 第一步:下载zookeeper:zookeeper的下载地址: http://mirror.bit.edu.cn/apache/zookeeper/ 第二步:安装: ...

  4. nodejs实现静态托管

    const express = require("express"); const app = express(); /* 语法1: app.use(express.static( ...

  5. 何为RunLoop?RunLoop有哪些应用场景?

    一.RunLoop的作用 一个应用开始运行以后放在那里,如果不对它进行任何操作,这个应用就像静止了一样,不会自发的有任何动作发生,但是如果我们点击界面上的一个按钮,这个时候就会有对应的按钮响应事件发生 ...

  6. INSPIRED启示录 读书笔记 - 第12章 产品探索

    软件项目可以划分为两个阶段 探索产品阶段:弄清楚要开发什么产品(定义正确的产品) 在探索产品的阶段,产品经理负责分析各种创意,广泛收集用户需求,了解如何运用新技术,拿出产品原型并加以测试 从全局视角思 ...

  7. Kubernetes List-Watch

    list-watch,作为k8s系统中统一的异步消息传递方式,对系统的性能.数据一致性起到关键性的作用. list-watch操作需要做这么几件事: 由组件向apiserver而不是etcd发起wat ...

  8. Codeforces Round #425 (Div. 2) D 树链剖分 + 树状数组维护区间

    一看就知道 可以LCA判断做 也可以树链剖分拿头暴力 然而快速读入和线段树维护区间会T70 于是只能LCA? 线段树的常数不小 于是需要另外一种办法来进行区间加减和查询区间和 就是使用树状数组 这个题 ...

  9. JMeter设置Http代理对web或者app进行录制

    一.录制web 1.首先保证JMeter的安装环境都正确.启动JMeter:在安装路径的bin目录下双击jmeter.bat (例如:D:\apache-jmeter-2.13\bin) ​2.打开J ...

  10. java异常中的finally(一)

    finally是保证语句能一定执行的.不管程序是否会报错,我们把程序一定要执行的代码放在finally中. 比如说流的关闭,不管在读写的过程中是否报错,一定要关闭流,可以把流的关闭操作放在finall ...