zoukankan      html  css  js  c++  java
  • 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++='
    ';return;}
     13     register int tp=0;while(a)num[tp++]=a%10,a/=10;
     14     while(tp--)*outs++=num[tp]+'0';*outs++='
    ';    
     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
    ",ans);
    194     }
    195     return 0;
    196 }
    View Code
  • 相关阅读:
    C-Scanf连续调用多次并且存在%c的问题
    JavaScript-常用正则函数(适合忘记时看)
    JavaScript-深入理解JavaScript(一、预编译和执行过程)
    Python-代码性能优化技巧
    Python-深入理解元类(metaclass)
    Python-编码之大彻大悟
    Python-正确使用Unicode
    Fiddler-抓取安卓手机APP请求地址
    unity, access sprite of UGUI Image
    unity, UGUI Text outline
  • 原文地址:https://www.cnblogs.com/Ren-Ivan/p/8276934.html
Copyright © 2011-2022 走看看