【WC2014】紫荊花之戀
第二道點分題就切紫荊花之戀真的好嗎…
題意: 在一棵樹上不斷加入一個節點[共
思路正如政治老師所說:
令r爲當前根,則
dist(i,j)⩽ri+rj⇔dist(i,r)−ri⩽rj−dist(j,r)
所以可以用一個數據結構維護當前根的所有dist(i,r)−ri ,以及當前子樹對於上一層根的dist(i,r)−ri ,對於每一個rj−dist(j,r) 查詢兩次並求差[跨根的路徑兩端不在同一子樹]即可。
所以,最後我們得到了一個通過 動態點分治+樹堆+倍增[LCA]+替罪羊樹 實現的時間複雜度均攤
#include<ctime>
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<sys/time.h>
using namespace std;
typedef long long ll;
#define OJ
//#define TM
//#define TM2
ll ctime()
{
#ifdef TM
return clock();
#else
#ifdef TM2
return clock();
#else
return 0LL;
#endif
#endif
}
inline ll rd()
{
static ll r, c;
for(r=0;(c=getchar())<48||57<c;);
for(;c>47&&58>c; r=10*r+c-48, c=getchar());
return r;
}
ll wr(ll x)
{
if(x/10) wr(x/10);
putchar(48+x%10);
}
inline ll maxx(ll &x, ll y) {x<y?x=y:0;}
const ll mxn=100008;
ll n, cte, ans=0, r[mxn];
struct edge{ll v, c; edge *o;} e[mxn<<1], *h[mxn];
inline ll ae(ll u, ll v, ll c)
{
(e[++cte]=
(edge){v, c, h[u]}, h[u]=e+cte);
}
#define forv for(i=u[h]; i&&(v=i->v); i=i->o)
//---------------------LCA---------------------
struct lca
{
const static ll mxlg=18;
ll dp[mxn], f[mxn][mxlg], ds[mxn];
ll sec, del;//time
ll init(ll u)
{
// del=ctime();//time
for(ll i=0, v; v=u[f][i]; ++i)
u[f][i+1]=v[f][i];
// sec+=ctime()-del;//time
}
inline ll dis(ll u, ll v)
{
// del=ctime();//time
static ll i, w, x, y; x=u, y=v,
dp[u]<dp[v]?u^=v^=u^=v:0;
for(i=mxlg-1; dp[u]-dp[v]; --i)
dp[u]-dp[v]&1<<i?u=f[u][i]:0;
for(i=mxlg-1; f[u][0]^f[v][0]; --i)
f[u][i]^f[v][i]?
u=f[u][i], v=f[v][i]:0;
w=u^v?f[u][0]:u;
// sec+=ctime()-del;//time
return ds[x]+ds[y]-2*ds[w];
}
} l;
//---------------------LCA---------------------
//---------------------splay-------------------
struct spl
{
const static ll mxnd=20000006;
ll f[mxnd], s[mxnd][2],
c[mxnd], siz[mxnd], cnt[mxnd],
nd, t, st[mxnd];//w=upperbound
// ll sec, del, cnto;//time
inline ll mt(ll u)
{u[siz]=u[s][0][siz]+u[s][1][siz]+u[cnt];}//VI
inline ll rtt(ll u)
{
static ll v, w, k;
v=f[u], k=v[s][1]==u,
(w=u[f]=v[f])?w[s][w[s][1]==v]=u:0,
(v[s][k]=u[s][!k])?v[s][k][f]=v:0,
(u[s][!k]=v)[f]=u,
mt(v), mt(u);
}
inline ll splay(ll u)
{
static ll v, w;
for(;v=u[f]; rtt(u))
(w=v[f])?rtt(v[s][0]==u^
w[s][0]==v?u:v):0;
}
inline ll nw1(ll &u, ll v=0)
{return s[u=++nd][0]=s[u][1]=
siz[u]=cnt[u]=0, f[u]=v, u;}
inline ll nw2(ll u, ll x)
{return ++siz[u], ++cnt[u], c[u]=x, u;}
inline ll ins(ll &u, ll x)
{
static ll v;
for(v=u; v&&c[u]^x;)
u=v, v=v[s][v[c]<=x];
u?splay(c[u]^x?
u[s][c[u]<x]=nw1(v, u):(v=u)):
nw1(v), nw2(u=v, x);
}
inline ll sum(ll &u, ll x)
{
static ll v;
for(v=u; v&&c[u]^x;)
u=v, v=v[s][v[c]<=x];
return splay(u),
u[s][0][siz]+(u[c]<=x?u[cnt]:0);
}//VI
ll erase(ll u)
{
u?(erase(u[s][0]), erase(u[s][1]),
st[t++]=u):0;
}
inline ll clear(ll u)
{
// del=ctime();//time
erase(u);
// sec+=ctime()-del;//time
}
};
//---------------------splay-------------------
//---------------------treap-------------------
struct node
{
node *s[2];
ll c, ky, siz, cnt;
};
struct tre
{
const static ll mxnd=10000006;
node t[mxnd], *st[mxnd];
ll nd, tp;
inline node* mt(node *&u)
{return u->siz=u->cnt+
(u->s[0]?u->s[0]->siz:0)+
(u->s[1]?u->s[1]->siz:0), u;}//VI
inline node* rtt(node *&u, ll k)
{
// printf("rotate:\n%d\n", u);
static node *v;
return u->s[k]=(v=u->s[k])->s[!k],
v->s[!k]=u, mt(u), mt(u=v);
}
inline node* nw1(node *&u, ll x)
{return u=tp?st[--tp]:++nd+t,
*u=(node){0, 0, x, rand(), 1, 1}, u;}
inline node* nw2(node *&u)
{return ++u->siz, ++u->cnt, u;}
#define ku (u->c<=x)
node* ins(node *&u, ll x)
{
if(!u) return nw1(u, x);
if(u->c==x) return nw2(u);
ll k=ku;
ins(u->s[k], x);
if(u->s[k]->ky<u->ky) rtt(u, k);
else mt(u);
}
ll sum(node *u, ll x)
{
if(!u) return 0;
ll k=ku;
return sum(u->s[k], x)+
(k?(u->s[0]?u->s[0]->siz:0)+
u->cnt:0);
}
ll clear(node *u)
{
u?(clear(u->s[0]), clear(u->s[1]),
st[tp++]=u):0;
}
} s;
//---------------------treap-------------------
//---------------------點分治建樹--------------
struct ppt
{
ll m, rt, fa, csrt,
dep[mxn], sz[mxn], fat[mxn],
t, st[mxn];
node *st1[mxn], *st2[mxn];//splay tree 1 and 2
// ll cntc;//time
ll grt(ll u, ll f)
{
edge *i; ll v, csu=0; sz[u]=1;
forv if(v^f&&!dep[v]) grt(v, u),
sz[u]+=sz[v], maxx(csu, sz[v]);
maxx(csu, m-sz[u]);
if(csu<csrt) rt=u, fa=f, csrt=csu;//VI
}
ll dfs(ll u, ll f, ll d)
{
edge *i; ll v; st[t++]=d-r[u];
forv if(v^f&&!dep[v])
dfs(v, u, d+i->c);
}
inline ll ins(node *&x, node *&y)
{
for(y=0; t;)
s.ins(x, st[--t]),
s.ins(y, st[t]);
}
ll build(ll u, ll f, ll d, node *st)
{
edge *i; ll v; m=sz[u], csrt=~(1<<31), grt(u, 0),
#ifdef TM
// printf("bui:%I64d %I64d\n", u, rt),
#endif
fa?sz[fa]=m-sz[u=rt]:0, sz[u]=m,//VI
dep[u]=d, fat[u]=f,//VI
s.ins(st1[u]=0x0, -r[u]), st2[u]=st;//VI
forv if(!dep[v]) dfs(v, 0, i->c),
ins(st1[u], st2[v]=0x0);
forv if(!dep[v])
build(v, u, d+1, st2[v]);
}
ll clear(ll u, ll f, ll d)
{
// ++cntc;//time
edge *i; ll v; dep[u]=0, s.clear(st1[u]),
d<=u[fat][dep]?s.clear(st2[u]):0;
forv if(v^f&&d<=dep[v])
clear(v, u, d);
}
} p;
//---------------------點分治建樹--------------
//---------------------動態點分治--------------
const double q=0.88;
#define stk (k^1?p.st2:p.st1)
inline ll qry(ll u, ll v, ll d, ll k)
{return s.sum(v[stk], r[u]-d);}
inline node* ins(ll u, ll v, ll d, ll k)
{return s.ins(v[stk], d-r[u]);}
ll cntr;
//ll sec, sec2, del;//time
inline ll gans(ll u)
{
#ifdef TM
cntr=0;
printf("(%I64d)\n", ctime());
#endif
static ll v, w, d;
for(v=u, w=0; v; w=v, v=v[p.fat])
#ifdef TM
++cntr,
#endif
++p.sz[v], d=l.dis(u, v),//VI
ans+=qry(u, v, d, 1)-qry(u, w, d, 2),//v->w->>>u
ins(u, v, d, 1), w&&ins(u, w, d, 2);
wr(ans), putchar('\n');
#ifdef TM
printf("{%I64d, %I64d}\n", l.sec, s.sec);
printf("[%I64d]\n", cntr);
printf("(%I64d)\n\n", ctime());
#endif
for(v=w=0; u; w=u, u=p.fat[u])
p.sz[w]>q*p.sz[u]?v=u:0;
v?(
// puts("rebuild"),
#ifdef TM
del=ctime(),//time
#endif
p.clear(v, 0, w=p.dep[v]),
#ifdef TM
sec2+=ctime()-del,//time
#endif
p.build(v, p.fat[v], w, p.st2[v])
#ifdef TM
, printf("af:%d\n\n", sec+=ctime()-del)//time
#endif
):0;
}
//---------------------動態點分治--------------
inline ll add(ll u, ll f, ll c, ll ru)
{
ae(u, f, c), ae(f, u, c), r[u]=ru,//VI L
l.f[u][0]=f, l.dp[u]=l.dp[f]+1,//VI L
l.ds[u]=l.ds[f]+c, l.init(u),//VI L
p.fat[u]=f, p.dep[u]=p.dep[f]+1;//VI P
}
namespace debug
{
static ll sz[mxn], i, k;
ll chk(ll u)
{
// if(!u) return 0LL;
// if(u[s.s][0]&&u[s.s][0][s.c]>=u[s.c]||
// u[s.s][1]&&u[s.c]>=u[s.s][1][s.c]) return 1LL;
// if(u[s.s][0][s.siz]+u[s.s][1][s.siz]+u[s.cnt]!=u[s.siz]) return 1LL;
// return chk(u[s.s][0])|chk(u[s.s][1]);
}
inline ll chk()
{
// for(i=1; i<=n; ++i)
// sz[i]=1;
// for(i=1; i<=n; ++i)
// sz[p.fat[i]]+=p.sz[i];
// for(i=1; i<=n; ++i)
// printf("%I64d:%I64d %I64d\n", i, p.sz[i], sz[i]);
// for(i=1; i<=n; ++i)
// printf("%I64d->%I64d\n", i, i[p.fat]);
// for(k=0, i=1; i<=3243; ++i)
// k|=chk(p.st1[i])|chk(p.st2[i]);
// printf("k:%I64d\n", k);
// printf("%d %d %d\n", s.siz[0], s.c[0], s.cnt[0]);
}
}
int main()
{
#ifndef OJ
using namespace debug;
freopen("55.in", "r", stdin);
freopen("55-1.out", "w", stdout);
#endif
srand(666233);
ll i, a, c, r;
rd(), n=rd();
for(i=1; i<=n; ++i)
{
a=rd()
#ifdef OJ
^ans%1000000000
#endif
, c=rd(), r=rd(),
add(i, a, c, r),
#ifdef TM
printf("case:%d\n{\n", i),
#endif
gans(i);
#ifdef TM
printf("}\n", i);
#endif
}
#ifndef OJ
#ifdef TM
freopen("CON", "w", stdout);
cout<<ctime()<<"\n";
cout<<"l:"<<l.sec<<"\ns:"<<s.sec<<"\np:"<<sec<<"\np2:"<<sec2<<"\nc:"<<p.cntc<<"\n";
p.sz[1]=n, p.clear(1, 0, 1); sec=ctime();
ll x=s.cnto, y=s.sec;
p.build(1, 0, 1, 0);
printf("b:%I64d\ns:%I64d\no:%I64d\n",
ctime()-sec, s.sec-y, s.cnto-x); chk();
#else
#ifdef TM2
freopen("CON", "w", stdout);
cout<<ctime()<<"\n";
#endif
#endif
#endif
return 0;
}