bzoj3435 [Wc2014]紫荆花之恋
如果这棵树不变的话,就是一个裸的点分树套平衡树,式子也很好推$di+dj<=ri+rj$,$ri-di>=dj-rj$ 平衡树维护$dj-rj$,然后查$ri-di$的$rank$即可。
但是点分树如果极度不平衡也就没有什么意义了。所以利用替罪羊树的思想,当某个子树极度不平衡时,就重新找重心,重建点分树。时间复杂度$O(nlg^2n)$,无旋Treap被卡,有旋Treap常数十分优秀。
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<algorithm> 5 #include<cmath> 6 using namespace std; 7 #define L 1<<20 8 char _buf[L],*SS,*TT,c; 9 const int BufS=3000000,md=1000000000; 10 char buf[BufS],*inss=buf,*outs=buf,num[10]; 11 inline void pl(register long long a){ 12 if(!a){*outs++='0',*outs++='\n';return;} 13 register int tp=0;while(a)num[tp++]=a%10,a/=10; 14 while(tp--)*outs++=num[tp]+'0';*outs++='\n'; 15 } 16 #define gc() (SS==TT&&(TT=(SS=_buf)+fread(_buf,1,L,stdin),SS==TT)?0:*SS++) 17 int get() 18 { 19 for(c=gc();c<'0'||c>'9';c=gc()); 20 int x=c^'0'; 21 for(c=gc();c>='0'&&c<='9';c=gc())x=x*10+(c^'0'); 22 return x; 23 } 24 #define N 100050 25 int n; 26 long long ans; 27 namespace Treap{ 28 #define tp pair<Node*,Node*> 29 struct Node{ 30 Node *ch[2]; 31 int key,val,size; 32 void pushup(){ 33 size=ch[0]->size+ch[1]->size+1; 34 } 35 Node(int k); 36 }*null=new Node(0),*root[N],*root1[N]; 37 Node :: Node(int k){ 38 key=k;val=rand();size=1; 39 ch[0]=ch[1]=null; 40 } 41 void init(){ 42 null->ch[0]=null->ch[1]=null; 43 null->key=null->val=null->size=0; 44 for(int i=0;i<=::n;i++)root[i]=root1[i]=null; 45 } 46 int getrank(Node *now,int x){ 47 int ans=0; 48 while(now!=null){ 49 if(now->key<x)ans+=now->ch[0]->size+1,now=now->ch[1]; 50 else now=now->ch[0]; 51 } 52 return ans; 53 } 54 void rotate(Node *&x,int d){ 55 Node *y=x->ch[d]; 56 x->ch[d]=y->ch[d^1]; 57 y->ch[d^1]=x; 58 x->pushup();y->pushup(); 59 x=y; 60 } 61 void insert(Node *&rt,int x){ 62 if(rt==null)rt=new Node(x); 63 else{ 64 int d=x>rt->key; 65 insert(rt->ch[d],x); 66 if(rt->ch[d]->val<rt->val)rotate(rt,d); 67 } 68 rt->pushup(); 69 } 70 void dfs(Node *rt){ 71 if(rt==null)return; 72 dfs(rt->ch[0]); 73 dfs(rt->ch[1]); 74 delete rt; 75 } 76 } 77 int head[N],e=1; 78 struct edge{ 79 int v,next; 80 }ed[N<<1]; 81 void add(int u,int v){ 82 ed[e].v=v;ed[e].next=head[u]; 83 head[u]=e++; 84 } 85 int dep[N],val[N],fa[N][20],r[N],w[N]; 86 int lca(int x,int y){ 87 if(dep[x]<dep[y])swap(x,y); 88 for(int i=17;~i;i--) 89 if(dep[fa[x][i]]>=dep[y])x=fa[x][i]; 90 if(x==y)return x; 91 for(int i=17;~i;i--) 92 if(fa[x][i]!=fa[y][i])x=fa[x][i],y=fa[y][i]; 93 return fa[x][0]; 94 } 95 int dis(int x,int y){ 96 return val[x]+val[y]-2*val[lca(x,y)]; 97 } 98 int size[N],maxn[N],root,sum; 99 bool vis[N]; 100 int f[N],S[N]; 101 void getroot(int x,int fa){ 102 size[x]=1;maxn[x]=0; 103 for(int i=head[x];i;i=ed[i].next){ 104 int v=ed[i].v; 105 if(v==fa||!vis[v])continue; 106 getroot(v,x); 107 size[x]+=size[v]; 108 maxn[x]=max(maxn[x],size[v]); 109 } 110 maxn[x]=max(maxn[x],sum-size[x]); 111 if(maxn[x]<maxn[root])root=x; 112 } 113 void init(int x,int fa){ 114 f[x]=fa;vis[x]=0; 115 int all=sum; 116 for(int i=head[x];i;i=ed[i].next){ 117 int v=ed[i].v; 118 if(!vis[v])continue; 119 sum=size[v]<size[x]?size[v]:all-size[x]; 120 root=0; 121 getroot(v,0); 122 init(root,x); 123 } 124 } 125 int T,tim[N]; 126 void dfs1(int x,int fa,int s){ 127 vis[x]=1;sum++;S[x]=0;tim[x]=T; 128 dfs(Treap::root[x]);Treap::root[x]=Treap::null; 129 dfs(Treap::root1[x]);Treap::root1[x]=Treap::null; 130 for(int i=head[x];i;i=ed[i].next){ 131 int v=ed[i].v; 132 if(v==fa||S[v]>s)continue; 133 dfs1(v,x,s); 134 } 135 } 136 void dfs2(int x,int fa,int en){ 137 int now=x; 138 while(now!=en){ 139 S[now]++; 140 Treap::insert(Treap::root[now],dis(x,now)-r[x]); 141 if(f[now])Treap::insert(Treap::root1[now],dis(x,f[now])-r[x]); 142 now=f[now]; 143 } 144 for(int i=head[x];i;i=ed[i].next){ 145 int v=ed[i].v; 146 if(v==fa||tim[v]!=T)continue; 147 dfs2(v,x,en); 148 } 149 } 150 void rebuild(int x){ 151 int fa=f[x];T++;sum=0; 152 dfs1(x,0,S[x]);root=0; 153 getroot(x,0); 154 init(root,fa); 155 dfs2(x,0,fa); 156 } 157 int query(int x){ 158 int now=x; 159 int cnt=getrank(Treap::root[now],r[x]+1); 160 while(f[now]){ 161 cnt+=Treap::getrank(Treap::root[f[now]],r[x]-dis(x,f[now])+1) 162 -Treap::getrank(Treap::root1[now],r[x]-dis(x,f[now])+1); 163 now=f[now]; 164 } 165 return cnt-1; 166 } 167 void insert(int x){ 168 if(x>1)add(x,f[x]),add(f[x],x); 169 fa[x][0]=f[x]; 170 dep[x]=dep[fa[x][0]]+1; 171 val[x]=val[f[x]]+w[x]; 172 for(int i=1;(1<<i)<=dep[x];i++) 173 fa[x][i]=fa[fa[x][i-1]][i-1]; 174 S[x]++; 175 int now=x,ret=0; 176 while(f[now]){ 177 Treap::insert(Treap::root[now],dis(x,now)-r[x]); 178 Treap::insert(Treap::root1[now],dis(x,f[now])-r[x]); 179 S[f[now]]++; 180 if(S[now]>S[f[now]]*0.88)ret=f[now]; 181 now=f[now]; 182 }Treap::insert(Treap::root[now],dis(x,now)-r[x]); 183 if(ret)rebuild(ret); 184 ans+=query(x); 185 } 186 int main(){ 187 n=get();n=get();maxn[0]=N; 188 Treap::init(); 189 for(int i=1;i<=n;i++){ 190 f[i]=get();w[i]=get();r[i]=get(); 191 f[i]=f[i]^(ans%1000000000); 192 insert(i); 193 printf("%lld\n",ans); 194 } 195 return 0; 196 }
人生如梦亦如幻 朝如晨露暮如霞。