[WC2014]紫荆花之恋
2018-03-10 22:09
260 查看
题意:每次插入一个点,询问dis(i,j)≤ri+rjdis(i,j)≤ri+rj的数量
①:假装这棵树是一开始给你的
树上路径问题−>−>点分治
考虑重心uu,答案就是dis(i,u)+dis(u,j)≤ri+rjdis(i,u)+dis(u,j)≤ri+rj的数量
移一个项⇒dis(i,u)−ri≤rj−dis(u,j)⇒dis(i,u)−ri≤rj−dis(u,j)
把所有的dis(i,u)−ridis(i,u)−ri插入uu的平衡树,询问uu的平衡树中rj−dis(u,j)rj−dis(u,j)的排名就好了
计算贡献什么的基本都是点分治的基本套路(其实主要是这部分大家都讲得很清楚了)
②:这棵树会动怎么做?
考虑用按照替罪羊树的思想,从这个点不断跳上一层重心,当满足Szi>Szfai∗αSzi>Szfai∗α时就重构faifai这棵树,当然faifai要是最浅的
③:细节&卡常
听起来似乎好简单(想完题解后我也是这么想的),但是写起来写到怀疑人生
我们讲一讲这道题最要命的地方——细节&卡常
1.1.你需要一颗高效的平衡树,可能你80−9080−90分,这时候换一颗平衡树说不定就卡过了;如果你用TreapTreap的话不如手写随机会快一些
2.2.你需要一个平衡树的垃圾桶,因为这题重构是要清空这棵树以及这棵树上每个节点的平衡树的,这里会造成巨大的空间浪费(其实你不写垃圾桶你可能会被卡到MLEMLE)
3.3.我稍微感受了一下平衡树写法的速度大概是这样的:结构体>>指针>>数组
其实想想也比较好理解吧
4.4.对于像我一样的手残党,一开始写代码的时候最好还是写到namespacenamespace里面吧,之前因为平衡树节点的sizesize用szsz当名字,然后点分治按照习惯也写的szsz,后来发现重名了,然后就稍微改了一下,然后有一个地方没有改,但是他小数据跑出来了exm?!?!exm?!?!,然后调到绝望才找出来.什么你说那样不好看??你不知道先写完保证不错然后ctrl+Fctrl+F替换吗?
5.5.什么你问我为什么第一名那么快??其实主要是处理链的部分非常快
因为我们可以发现链完全不要像上面那么做
假设11是链的顶端,左右分别拉一条链,令di=dis(1,i)di=dis(1,i)
考虑新加进来的点一定在链的底端,考虑两种情况
du−di≤ru+ri⇒−di−ri≤ru−du,udu−di≤ru+ri⇒−di−ri≤ru−du,u和ii在同一边
du+di≤ru+ri⇒di−ri≤ru−du,udu+di≤ru+ri⇒di−ri≤ru−du,u和ii在不同边
所以你维护44棵平衡树就可以在O(nlogn)O(nlogn)的时间内处理出答案了
注意要特判当du≤r1+rudu≤r1+ru时答案要减11
6.6.卡常有风险,codecode需谨慎
7.7.什么你说还不够快??那你可以用bfsbfs来求重心,不要用STLSTL,能放在一块的用结构体存起……
至于代码的话将就着看吧
①:假装这棵树是一开始给你的
树上路径问题−>−>点分治
考虑重心uu,答案就是dis(i,u)+dis(u,j)≤ri+rjdis(i,u)+dis(u,j)≤ri+rj的数量
移一个项⇒dis(i,u)−ri≤rj−dis(u,j)⇒dis(i,u)−ri≤rj−dis(u,j)
把所有的dis(i,u)−ridis(i,u)−ri插入uu的平衡树,询问uu的平衡树中rj−dis(u,j)rj−dis(u,j)的排名就好了
计算贡献什么的基本都是点分治的基本套路(其实主要是这部分大家都讲得很清楚了)
②:这棵树会动怎么做?
考虑用按照替罪羊树的思想,从这个点不断跳上一层重心,当满足Szi>Szfai∗αSzi>Szfai∗α时就重构faifai这棵树,当然faifai要是最浅的
③:细节&卡常
听起来似乎好简单(想完题解后我也是这么想的),但是写起来写到怀疑人生
我们讲一讲这道题最要命的地方——细节&卡常
1.1.你需要一颗高效的平衡树,可能你80−9080−90分,这时候换一颗平衡树说不定就卡过了;如果你用TreapTreap的话不如手写随机会快一些
2.2.你需要一个平衡树的垃圾桶,因为这题重构是要清空这棵树以及这棵树上每个节点的平衡树的,这里会造成巨大的空间浪费(其实你不写垃圾桶你可能会被卡到MLEMLE)
3.3.我稍微感受了一下平衡树写法的速度大概是这样的:结构体>>指针>>数组
其实想想也比较好理解吧
4.4.对于像我一样的手残党,一开始写代码的时候最好还是写到namespacenamespace里面吧,之前因为平衡树节点的sizesize用szsz当名字,然后点分治按照习惯也写的szsz,后来发现重名了,然后就稍微改了一下,然后有一个地方没有改,但是他小数据跑出来了exm?!?!exm?!?!,然后调到绝望才找出来.什么你说那样不好看??你不知道先写完保证不错然后ctrl+Fctrl+F替换吗?
5.5.什么你问我为什么第一名那么快??其实主要是处理链的部分非常快
因为我们可以发现链完全不要像上面那么做
假设11是链的顶端,左右分别拉一条链,令di=dis(1,i)di=dis(1,i)
考虑新加进来的点一定在链的底端,考虑两种情况
du−di≤ru+ri⇒−di−ri≤ru−du,udu−di≤ru+ri⇒−di−ri≤ru−du,u和ii在同一边
du+di≤ru+ri⇒di−ri≤ru−du,udu+di≤ru+ri⇒di−ri≤ru−du,u和ii在不同边
所以你维护44棵平衡树就可以在O(nlogn)O(nlogn)的时间内处理出答案了
注意要特判当du≤r1+rudu≤r1+ru时答案要减11
6.6.卡常有风险,codecode需谨慎
7.7.什么你说还不够快??那你可以用bfsbfs来求重心,不要用STLSTL,能放在一块的用结构体存起……
至于代码的话将就着看吧
#include<bits/stdc++.h> #define fp(i,a,b) for(int i=a,I=b+1;i<I;++i) #define fd(i,a,b) for(int i=a,I=b-1;i>I;--i) #define go(i,u) for(int i=fi[u],v=e[i].to;i;v=e[i=e[i].nx].to) #define file(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout) template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;} using namespace std; char ss[1<<17],*A=ss,*B=ss; inline char gc(){return A==B&&(B=(A=ss)+fread(ss,1,1<<17,stdin),A==B)?-1:*A++;} template<class T>inline void sd(T&x){ char c;T y=1;while(c=gc(),(c<48||57<c)&&c!=-1)if(c==45)y=-1;x=c-48; while(c=gc(),47<c&&c<58)x=x*10+c-48;x*=y; } char sr[1<<21],z[20];int C=-1,Z; inline void Ot(){fwrite(sr,1,C+1,stdout),C=-1;} template<class T>inline void we(T x){ if(C>1<<20)Ot();if(x<0)sr[++C]=45,x=-x; while(z[++Z]=x%10+48,x/=10); while(sr[++C]=z[Z],--Z);sr[++C]='\n'; } const int N=1<<17,L=30,M=35*N,P=1e9; const double alpha=0.777,beta=0.77; typedef int arr ; typedef long long ll; struct eg{int nx,to,w;}e[2*N]; int n,ce;arr R,fi;ll ans; inline void add(int u,int v,int w){e[++ce]=eg{fi[u],v,w},fi[u]=ce;} //Scapegoat Tree struct sgt{int sz,w,c[2];}tr[M];int cn,cb,bin[M]; inline int New(){return cb?bin[cb--]:++cn;} inline void up(int u){tr[u].sz=tr[tr[u].c[0]].sz+tr[tr[u].c[1]].sz+1;} inline void rot(int&u,int k){int v=tr[u].c[k];tr[u].c[k]=tr[v].c[!k],tr[v].c[!k]=u,up(u),up(u=v);} void ins(int&u,int w){ if(!u)return tr[u=New()]=sgt{1,w,{0,0}},void(); bool k=w>tr[u].w;++tr[u].sz;ins(tr[u].c[k],w);if(tr[tr[u].c[k]].sz>tr[u].sz*beta)rot(u,k); } inline int rk(int u,int w){if(!u)return 0;return w<tr[u].w?rk(tr[u].c[0],w):(tr[tr[u].c[0]].sz+1+rk(tr[u].c[1],w));} void cle(int&u){if(!u)return;bin[++cb]=u;cle(tr[u].c[0]);cle(tr[u].c[1]);u=0;} //Dynamic Divide struct dyd{int d,f[L],l[L];}g ; int rt,Sum,T [2];arr q,d,Sz,Fa,fx;bool vis ;vector<int>Tr ; void gr(int u,int fa){ fx[u]=0,Sz[u]=1; go(i,u)if(!vis[v]&&v^fa)gr(v,u),Sz[u]+=Sz[v],cmax(fx[u],Sz[v]); cmax(fx[u],Sum-Sz[u]);if(fx[u]<fx[rt])rt=u; } inline void bfs(int u){ int h=1,t=1;q[t]=u; while(h<=t){vis[u=q[h++]]=1;go(i,u)if(!vis[v])d[q[++t]=v]=d[u]+e[i].w;} q[0]=t;fp(i,1,t)vis[q[i]]=0; } inline void pb(int u,int f,int w){dyd&d=g[u];d.f[d.d]=f,d.l[d.d]=w,++d.d;} void sol(int u){ vis[u]=1;ins(T[u][0],-R[u]);Tr[u].push_back(u),pb(u,u,0); go(i,u)if(!vis[v]){ d[v]=e[i].w,bfs(v),Sum=Sz[v],gr(v,rt=0); fp(j,1,q[0])Tr[u].push_back(v=q[j]),ins(T[u][0],d[v]-R[v]),ins(T[rt][1],d[v]-R[v]),pb(v,u,d[v]); Fa[rt]=u,sol(rt); } } inline void Re(int u){ int*a=Tr[u].data(),NewSiz=g[Fa[u]].d,v; fp(i,1,Tr[u].size()-1){ vis[v=a[i]]=0,Tr[v].clear(); cle(T[v][0]),cle(T[v][1]); g[v].d=NewSiz; } Sum=Tr[u].size(),gr(u,rt=vis[u]=0); T[rt][1]=T[u][1];cle(T[u][0]);T[u][1]=0; Tr[u].clear();g[u].d=NewSiz;Fa[rt]=Fa[u];sol(rt); } inline void calc(int u,int f,int w){ add(u,f,w),add(f,u,w),Fa[u]=f;g[u]=g[f]; vis[u]=1;pb(u,u,-w);int*a=g[u].f,*b=g[u].l,p; fp(i,0,g[u].d-1){ b[i]+=w;Tr[p=a[i]].push_back(u); ans+=rk(T[p][0],R[u]-b[i])-(i?rk(T[p][1],R[u]-b[i-1]):0); ins(T[p][0],b[i]-R[u]);if(i)ins(T[p][1],b[i-1]-R[u]); }we(ans); fp(i,1,g[u].d-1)if(tr[T[a[i]][0]].sz>tr[T[a[i-1]][0]].sz*alpha)return Re(a[i-1]); } int a,b,wic,t[2][2],Chain[2]={1,1}; int main(){ #ifndef ONLINE_JUDGE file("s"); #endif sd(n),sd(n);int u=2;fx[0]=N,we(0); sd(a),sd(b),sd(R[1]);fp(i,0,1)fp(j,0,1)ins(t[i][j],-R[1]); for(;u<=n;++u){ sd(a),sd(b),sd(R[u]); #ifdef ONLINE_JUDGE a^=ans%P; #endif if(a^Chain[0]&&a^Chain[1])break; Fa[u]=a;add(u,a,b),add(a,u,b); wic=Fa[u]==Chain[1],Chain[wic]=u;d[u]=d[a]+b; ans+=rk(t[0][wic],R[u]-d[u])+rk(t[1][!wic],R[u]-d[u]); ins(t[0][wic],-d[u]-R[u]);ins(t[1][wic],d[u]-R[u]); if(d[u]<=R[1]+R[u])--ans;we(ans); }if(u<=n){ fp(i,0,1)fp(j,0,1)cle(t[i][j]); Sum=u-1;gr(1,0);Fa[rt]=0;sol(rt);calc(u,a,b); for(++u;u<=n;++u){ sd(a),sd(b),sd(R[u]); #ifdef ONLINE_JUDGE a^=ans%P; #endif calc(u,a,b); } } return Ot(),0; }
相关文章推荐
- Wc2014 紫荆花之恋
- NKOJ 2703 (WC 2014)紫荆花之恋 (点分治+平衡树+替罪羊)
- [替罪羊树 动态点分治 替罪羊式重构] BZOJ 3435 [Wc2014]紫荆花之恋 & UOJ #55 【WC2014】紫荆花之恋
- Wc2014 紫荆花之恋
- WC2014-紫荆花之恋
- BZOJ3435: [Wc2014]紫荆花之恋 动态树分治 替罪羊树
- [WC 2014]紫荆花之恋
- 数据结构(平衡树,树分治,暴力重构):WC 2014 紫荆花之恋
- 【BZOJ3435】【UOJ55】【WC2014】紫荆花之恋
- uoj#55./bzoj3435 【WC2014】紫荆花之恋 //替罪羊式重构点分树
- [BZOJ3435][Wc2014]紫荆花之恋-替罪羊树-treap-动态点分治
- bzoj3435 [Wc2014]紫荆花之恋
- bzoj 3435: [Wc2014]紫荆花之恋 替罪羊树维护点分治 && AC400
- bzoj3435 [Wc2014]紫荆花之恋
- bzoj3435 [Wc2014]紫荆花之恋(动态点分治+替罪羊树)
- 【BZOJ3435】[Wc2014]紫荆花之恋 替罪点分树+SBT
- BZOJ 3435: [Wc2014]紫荆花之恋
- BZOJ 3435 Wc2014 紫荆花之恋 动态树分治+替罪羊树+Treap
- wc2014 紫荆花之恋
- BZOJ3435 & 洛谷3920 & UOJ55:[WC2014]紫荆花之恋