【 [Wc2014]紫荆花之恋】(⊙o⊙)动态点分治重构
久闻紫荆花之恋大名,今日一见,果然名不虚传,不过名字确实挺美的owo
luogu3920
UOJ55
3435: [Wc2014]紫荆花之恋
Time Limit: 240 Sec Memory Limit: 512 MB Submit: 688 Solved: 235 [Submit][Status][Discuss]Description
强强和萌萌是一对好朋友。有一天他们在外面闲逛,突然看到前方有一棵紫荆树。这已经是紫荆花飞舞的季节了,无数的花瓣以肉眼可见的速度从紫荆树上长了出来。仔细看看的话,这个大树实际上是一个带权树。每个时刻它会长出一个新的叶子节点。每个节点上有一个可爱的小精灵,新长出的节点上也会同时出现一个新的小精灵。小精灵是很萌但是也很脆弱的生物,每个小精灵 i 都有一个感受能力值Ri ,小精灵 i, j 成为朋友当且仅当在树上 i 和 j 的距离 dist(i,j) ≤ Ri + R! ,其中 dist(i, j)表示在这个树上从 i 到 j 的唯一路径上所有边的边权和。强强和萌萌很好奇每次新长出一个叶子节点之后,这个树上总共有几对朋友。
我们假定这个树一开始为空,节点按照加入的顺序从 1开始编号。由于强强非常好奇, 你必须在他每次出现新节点后马上给出总共的朋友对数,不能拖延哦。
Input
共有 n + 2 行。
第一行包含一个正整数,表示测试点编号。
第二行包含一个正整数 n ,表示总共要加入的节点数。
我们令加入节点前的总共朋友对数是 last_ans,在一开始时它的值为0。
接下来 n 行中第 i 行有三个数 ai, bi, ri,表示节点 i 的父节点的编号为 ai xor (last_ans mod 10^9) (其中xor 表示异或,mod 表示取余,数据保证这样操作后得到的结果介于 1到i – 1之间),与父节点之间的边权为 ci,节点 i 上小精灵的感受能力值为r!。
注意 a1 = c1 = 0,表示 1 号点是根节点,对于 i > 1,父节点的编号至少为1。
Output
包含 n 行,每行输出1 个整数, 表示加入第 i 个点之后,树上有几对朋友。
Sample Input
0
5
0 0 6
1 2 4
0 9 4
0 5 5
0 2 4
Sample Output
0
1
2
4
7
HINT
1<=Ci<=10000
Ai<=2*10^9
Ri<=10^9
N<=100000
我们发现有万恶之源--强制在线,我们如果不强制在线,就是一个套路的动态点分治了,同样每个点维护自己子树信息和到该子树到父亲的信息,对于lcax来说就是因为disi + disj<= ri + rj,也就是disi - ri <= rj - disj,我们把disi - ri加入平衡树里面,然后查询的时候查询rj - disj 的排名就可以了,但是,但是,但是orz。
好吧,这里我们就要用到替罪羊的思想了,不平衡就重构。就是把他管的那一颗点分子树信息全部消除,然后一个点分树新建,找重心,加入距离,恩,看上去似乎还好,也没什么。
只有自己调试的时候痛苦不已。我之前写的时候居然平衡树替罪羊一直重构都没起到作用,也就是说一直是不平衡树,居然能拿到90,,加上大家都说卡常,我还以为常数痴了,一直在卡常。没想到啊orz。
7500B LJ代码:
#include<stdio.h>
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<vector>
#include<map>
using namespace std;
typedef long long ll;
//
int JSCNT;
namespace bz{
const int maxn = 100005;
int fa[17][maxn],dep[maxn];ll dis[maxn];
int glca(int x,int y) {
if(dep[x]<dep[y]) swap(x,y);
int dd = dep[x] - dep[y];
for(int i=0;dd;i++,dd>>=1)
if(dd&1) x = fa[i][x];
if(x==y) return x;
for(int i=16;i>=0;i--)
if(fa[i][x]!=fa[i][y]) x=fa[i][x],y=fa[i][y];
return fa[0][x];
}
ll gdis(int x,int y) {
int lcc = glca(x,y);
return dis[x] + dis[y] - 2*dis[lcc];
}
void add(int x,int f,int C) {
dep[x] = dep[f] + 1; fa[0][x] = f; dis[x] = dis[f] + C;
for(int i=1;i<=16;i++) fa[i][x] = fa[i-1][fa[i-1][x]];
}
}
//
char buf[1<<20],*p1,*p2;
#define GC (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin),p1==p2)?0:*p1++)
inline ll _R()
{
char t=GC;
ll x=0;
while(!isdigit(t)) t=GC;
while(isdigit(t)) x=x*10+t-48,t=GC;
return x;
}
char pbuf[1<<20],*pp=pbuf;
void push(const char c) {
if(pp-pbuf==(1<<20)) fwrite(pbuf,1,(1<<20),stdout),pp=pbuf;
*pp++=c;
}
inline void _W(ll x) {
static int sta[35];
int top=0;
do{sta[top++]=x%10,x/=10;}while(x);
while(top) push(sta[--top]+'0');
push('\n');
}
//
namespace bt{
const int maxn = 4000005;
struct node{
node *ls,*rs;ll dat;int siz,ct;ll mx;
}z[maxn],*nul,*pool[maxn],**RT; int lj,tot;
void upd(node *&p) {
p->siz = p->ls->siz + p->rs->siz + p->ct;
p->mx = p->dat;
if(p->ls!=nul) p->mx = max(p->ls->mx,p->mx);
if(p->rs!=nul) p->mx = max(p->rs->mx,p->mx);
}
vector<int>ve[maxn];
bool isbad(node *&p) {
if(max(p->ls->siz,p->rs->siz)>p->siz*0.88) return 1;
return 0;
}
node* nwnode(int x) {
node *p = lj?pool[lj--]:&z[++tot];
p->ls = p->rs = nul; p->siz = p->ct = 1; p->dat = p->mx = x;
return p;
}
void ins(node *&p,int x) {
if(p==nul) {
p = nwnode(x);
return ;
}
if(x==p->dat) p->ct++;
else if(x<p->dat) ins(p->ls,x);
else ins(p->rs,x);
if(isbad(p)) RT = &p;
upd(p);
}
ll lower(node*&p,ll x) {
if(p==nul) return 0;
if(p->mx<=x) return p->siz;
if(p->dat==x) return p->ls->siz + p->ct;
if(p->dat<x) return p->ls->siz + p->ct + lower(p->rs,x);
return lower(p->ls,x);
}
void init() {
nul=z; nul->ls=nul->rs=nul;
}
int stad[maxn],stac[maxn],tp;
void tra(node *&p) {
if(p==nul) return;
tra(p->ls);
++tp;
stad[tp] = p->dat; stac[tp]=p->ct;
pool[++lj]=p;
tra(p->rs);
}
void build(node *&p,int l,int r) {
int mid = (l+r)>>1;
p = nwnode(stad[mid]);
p->ct = p->siz = stac[mid];
if(l<mid) build(p->ls,l,mid-1);
if(mid<r) build(p->rs,mid+1,r);
upd(p);
}
void rebuild() {
tp=0;
tra(*RT);
build(*RT,1,tp);
RT = &nul;
}
node *sont[maxn],*treet[maxn]; // sont --> to father treet --> to it
void add(node *&p,int x) {
RT = &nul;
ins(p,x);
if(*RT!=nul) rebuild();
}
void clr(node *&p) {
tp = 0;
tra(p);
p = nul;
}
}//
int n;
namespace dft{
const int maxn = 300005;
int r[maxn];
int la[maxn],owo,en[maxn],nt[maxn],len[maxn];
int vis[maxn],vivi[maxn],tim;
void adg(int x,int y,int le) {
en[++owo]=y; nt[owo]=la[x]; la[x]=owo; len[owo]=le;
en[++owo]=x; nt[owo]=la[y]; la[y]=owo; len[owo]=le;
}
vector<int>sons[maxn];
int fa[maxn],VV;
void fuckall(int x) {
vis[x] = tim;
bt::clr(bt::treet[x]);
for(auto y:sons[x]) {
if(fa[y]!=x) continue;
fuckall(y);
bt::clr(bt::sont[y]);
}
sons[x].clear();
}
int rtsz,rrt,sm,sz[maxn];
void gsi(int x,int ba) {
sz[x]=1;
for(int it=la[x];it;it=nt[it]){
int y = en[it];
if(vis[y]!=tim||vivi[y]==tim||y==ba) continue;
gsi(y,x); sz[x] += sz[y];
}
}
void grt(int x,int ba) {
int sso = 0;
for(int it=la[x];it;it=nt[it]) {
int y = en[it];
if(vis[y]!=tim||vivi[y]==tim||y==ba) continue;
grt(y,x); sso = max(sso,sz[y]);
}
sso = max(sso,sm-sz[x]);
if(sso<rtsz) rtsz=sso,rrt=x;
}
void insdeep(int x,int ba,ll dd) {
bt::stad[++bt::tp]=dd-r[x];
for(int it=la[x];it;it=nt[it]) {
int y = en[it];
if(vis[y]!=tim||vivi[y]==tim||y==ba) continue;
insdeep(y,x,dd+len[it]);
}
}
void jianli(bt::node *&p) {
if(!bt::tp) return;
sort(bt::stad+1,bt::stad+1+bt::tp);
int now = 1; bt::stac[1] = 1;
for(int i=2;i<=bt::tp;i++) {
if(bt::stad[i]==bt::stad[now]) bt::stac[now]++;
else bt::stad[++now]=bt::stad[i],bt::stac[now]=1;
}
bt::build(p,1,now);
}
void DC(int x) {
vivi[x] = tim;
bt::tp = 0;
insdeep(x,0,0);
jianli(bt::treet[x]);
for(int it=la[x];it;it=nt[it]) {
int y = en[it];
if(vis[y]!=tim||vivi[y]==tim) continue;
gsi(y,x); sm=sz[y]; rtsz=0x3f3f3f3f;
grt(y,x); int p = rrt;
bt::tp = 0;
insdeep(y,x,len[it]);
jianli(bt::sont[p]);
DC(p); fa[p] = x;
sons[x].push_back(p);
}
}
int FRT=1;
void rebuild(int x) {
int ff = fa[x];
++tim;
bt::node* p = bt::sont[x];
bt::sont[x]= bt::nul;
fuckall(x);
gsi(x,0);
sm = sz[x]; rtsz=0x3f3f3f3f;
grt(x,0);
x = rrt;
bt::sont[x]=p;
zz:DC(x);
if(ff)sons[ff].push_back(x);
fa[x] = ff;
FRT = x;
}
int insert(int x,int f) {
bt::sont[x] = bt::nul; bt::treet[x] = bt::nul;
ll ans = 0;
sons[f].push_back(x);
fa[x] = f; ll dd,d=0;
for(int p=x;p;p=fa[p]) {
dd = d;
if(fa[p]) {
d = bz::gdis(x,fa[p]);
ans += bt::lower(bt::treet[fa[p]],r[x]-d);
ans -= bt::lower(bt::sont[p],r[x]-d);
bt::add(bt::sont[p],d-r[x]);
}
// dd = bz::gdis(x,p);
bt::add(bt::treet[p],dd-r[x]);
}
int rere = 0;
for(int p=x;fa[p];p=fa[p]) {
if(bt::treet[p]->siz>bt::treet[fa[p]]->siz*0.88) rere = fa[p];
}
if(rere)rebuild(rere);
return ans;
}
}
int main() {
// freopen("aa.in","r",stdin);
bt::init();
int ozozoz;
ozozoz=_R();n=_R();
ll lastans = 0;
for(int i=1;i<=n;i++) {
ll A,C,R; A=_R();C=_R();R=_R();
dft::r[i] = R;
A^=(int)(lastans%((long long)1e9));
if(A!=0)bz::add(i,A,C); if(A!=0)dft::adg(i,A,C);
lastans += dft::insert(i,A);
_W(lastans);
}
fwrite(pbuf,1,pp-pbuf,stdout);
// cout<<JSCNT;
}

浙公网安备 33010602011771号