• 各种树模板(splay,线段树,可持久化线段树...)


    Splay

    AC tyvj1728 普通平衡树


      1 #include <cstdio>
      2 #include <iostream>
      3 #include <fstream>
      4 
      5 #include <cstdlib>
      6 #include <cstring>
      7 #include <cmath>
      8 #include <algorithm>
      9 
     10 typedef long long int ll;
     11 typedef double db;
     12 
     13 using namespace std;
     14 
     15 struct SplayTree
     16 {
     17     struct node
     18     {
     19         int v;
     20         int tot;
     21         node*s[2];
     22         node*f;
     23         
     24         void update()
     25         {
     26             tot=s[0]->tot + s[1]->tot +1;
     27         }
     28     };
     29     node*pool;
     30     node*nt;
     31     node*nil;
     32     node*newnode(node*f,int v)
     33     {
     34         nt->v=v;
     35         nt->tot=1;
     36         nt->s[0]=nt->s[1]=nil;
     37         nt->f=f;
     38         return nt++;
     39     }
     40     
     41     node*root;
     42     
     43     SplayTree(int size)
     44     {
     45         pool=new node[size+1];
     46         nt=pool;
     47         nil=newnode(NULL,-1);
     48         nil->tot=0;
     49         nil->f=nil->s[0]=nil->s[1]=nil;
     50         root=nil;
     51     }
     52     
     53     //===============================================
     54     
     55     void update(node*x)
     56     {
     57         x->tot= x->s[0]->tot + x->s[1]->tot +1;
     58     }
     59     
     60     void rot(node*x)
     61     {
     62         if(x==nil) return ;
     63         
     64         node*y=x->f;
     65         int k=(x==y->s[0]);
     66         
     67         y->s[k^1]=x->s[k];
     68         if(x->s[k]!=nil) x->s[k]->f=y;
     69         
     70         x->f=y->f;
     71         if(y==y->f->s[0]) y->f->s[0]=x;
     72         else if(y==y->f->s[1]) y->f->s[1]=x;
     73         
     74         y->f=x;
     75         x->s[k]=y;
     76         
     77         y->update();
     78     }
     79     
     80     void splay(node*x) { splay(x,nil); }
     81     void splay(node*x,node*t)
     82     {
     83         if(x==nil) return ;
     84         while(x->f!=t)
     85         {
     86             node*y=x->f;
     87             if(y->f!=t) 
     88             if((x==y->s[0])^(y==y->f->s[0]))
     89                 rot(x); else rot(y);
     90             rot(x);
     91         }
     92         x->update();
     93         
     94         if(t==nil) root=x;
     95     }
     96     
     97     //=============================================
     98     
     99     void Insert(int v)
    100     {
    101         if(root==nil)
    102         {
    103             root=newnode(nil,v);
    104             return ;
    105         }
    106         
    107         node*x=root;
    108         node*y=x;
    109         while(x!=nil)
    110         {
    111             y=x;
    112             if(v<x->v) x=x->s[0];
    113             else x=x->s[1];
    114         }
    115         
    116         int k=!(v<y->v);
    117         y->s[k]=newnode(y,v);
    118         splay(y->s[k]);
    119     }
    120     
    121     
    122     node*Find(int v)
    123     {
    124         node*x=root;
    125         node*y=x;
    126         node*r=nil;
    127         while(x!=nil)
    128         {
    129             y=x;
    130             if(x->v==v) r=x;
    131             if(v<=x->v) x=x->s[0];
    132             else x=x->s[1];
    133         }
    134         splay(y);
    135         return r;
    136     }
    137     
    138     node* FindRank(int k)
    139     {
    140         node*x=root;
    141         node*y=x;
    142         while(x!=nil)
    143         {
    144             y=x;
    145             if(k==x->s[0]->tot+1) break;
    146             
    147             if(k<x->s[0]->tot+1)
    148                 x=x->s[0];
    149             else
    150             {
    151                 k-=x->s[0]->tot+1;
    152                 x=x->s[1];
    153             }
    154         }
    155         splay(y);
    156         return x;
    157     }
    158     
    159     int GetRank(node*x)
    160     {
    161         splay(x);
    162         return x->s[0]->tot+1;
    163     }
    164     
    165     int GetRevRank(node*x)
    166     {
    167         splay(x);
    168         return x->s[1]->tot+1;
    169     }
    170     
    171     node*Delete(node*x)
    172     {
    173         int k=GetRank(x);
    174         node*L=FindRank(k-1);
    175         node*R=FindRank(k+1);
    176         
    177         splay(L);
    178         splay(R,L);
    179         
    180         if(L==nil && R==nil) root=nil;
    181         else if(R==nil) L->s[1]=nil;
    182         else R->s[0]=nil;
    183         
    184         if(R!=nil) update(R);
    185         if(L!=nil) update(L);
    186         
    187         return x;
    188     }
    189     
    190     node*prefix(int v)
    191     {
    192         node*x=root;
    193         node*y=x;
    194         node*r=nil;
    195         while(x!=nil)
    196         {
    197             y=x;
    198             if(x->v<v) r=x;
    199             if(v<=x->v) x=x->s[0];
    200             else x=x->s[1];
    201         }
    202         splay(y);
    203         return r;
    204     }
    205     
    206     node*suffix(int v)
    207     {
    208         node*x=root;
    209         node*y=x;
    210         node*r=nil;
    211         while(x!=nil)
    212         {
    213             y=x;
    214             if(x->v>v) r=x;
    215             if(v<x->v) x=x->s[0];
    216             else x=x->s[1];
    217         }
    218         splay(y);
    219         return r;
    220     }
    221     
    222     
    223     
    224     
    225     //===========================================
    226     void output() { output(root); printf("%s\n",root==nil ? "empty tree!" : ""); }
    227     void output(node*x)
    228     {
    229         if(x==nil)return ;
    230         output(x->s[0]);
    231         printf("%d ",x->v);
    232         output(x->s[1]);
    233     }
    234     
    235     void test() { test(root); printf("%s\n",root==nil ? "empty tree!" : ""); }
    236     void test(node*x)
    237     {
    238         if(x==nil)return ;
    239         test(x->s[0]);
    240         printf("%p [ v:%d f:%p L:%p R:%p tot:%d ] \n",x,x->v,x->f,x->s[0],x->s[1],x->tot);
    241         test(x->s[1]);
    242     }
    243     
    244 };
    245 
    246 
    247 int n;
    248 
    249 int main()
    250 {
    251     scanf("%d",&n);
    252     SplayTree st(n);
    253     
    254     for(int i=0;i<n;i++)
    255     {
    256         int c;
    257         scanf("%d",&c);
    258         switch(c)
    259         {
    260             case 1: //Insert
    261                 scanf("%d",&c);
    262                 st.Insert(c);
    263             break;
    264             case 2: //Delete
    265                 scanf("%d",&c);
    266                 st.Delete(st.Find(c));
    267             break;
    268             case 3: //Rank
    269                 scanf("%d",&c);
    270                 printf("%d\n",st.GetRank(st.Find(c)));
    271             break;
    272             case 4: //FindRank
    273                 scanf("%d",&c);
    274                 printf("%d\n",st.FindRank(c)->v);
    275             break;
    276             case 5: //prefix
    277                 scanf("%d",&c);
    278                 printf("%d\n",st.prefix(c)->v);
    279             break;
    280             case 6: //suffix
    281                  scanf("%d",&c);
    282                  printf("%d\n",st.suffix(c)->v);
    283             break;
    284             case 7: //test
    285                 st.test();
    286             break;
    287             default: break; 
    288         } 
    289     }
    290 
    291     return 0;
    292 }
    View Code

     

    2015年2月19日更新:

    我现在才发现我写的双旋一直都是错的!!!!!

    记住如果是折线就两次rot(x),直线才是先y后x! if((x==y->s[0])^(y==y->f->s[0])) rot(x); else rot(y);


    要点1.别忘了有事没事splay一下保证复杂度.....

    要点2.各种if的顺序别搞混了!有些if是不能合并的.

    要点3.记住splay前的特判.如果要单独使用rotate就给rotate也加特判.

    要点4.不要有事没事就更改某些子树的位置!比如在delete的时候,提x作根,然后找到右子树最左边的节点后,合并左右两颗子树,这是会超时的!

     

    AC BZOJ 2733

     

      1 #include <cstdio>
      2 #include <fstream>
      3 #include <iostream>
      4  
      5 #include <cstdlib>
      6 #include <cstring>
      7 #include <algorithm>
      8 #include <cmath>
      9  
     10 #include <queue>
     11 #include <vector>
     12 #include <map>
     13 #include <set>
     14 #include <stack>
     15 #include <list>
     16 
     17 #include <bitset>
     18  
     19 typedef unsigned int uint;
     20 typedef long long int ll;
     21 typedef unsigned long long int ull;
     22 typedef double db;
     23  
     24 using namespace std;
     25  
     26 inline int getint()
     27 {
     28     int res=0;
     29     char c=getchar();
     30     bool mi=false;
     31     while(c<'0' || c>'9') mi=(c=='-'),c=getchar();
     32     while('0'<=c && c<='9') res=res*10+c-'0',c=getchar();
     33     return mi ? -res : res;
     34 }
     35 inline ll getll()
     36 {
     37     ll res=0;
     38     char c=getchar();
     39     bool mi=false;
     40     while(c<'0' || c>'9') mi=(c=='-'),c=getchar();
     41     while('0'<=c && c<='9') res=res*10+c-'0',c=getchar();
     42     return mi ? -res : res;
     43 }
     44 
     45 //==============================================================================
     46 //==============================================================================
     47 //==============================================================================
     48 //==============================================================================
     49 
     50 struct node*nil;
     51 struct node
     52 {
     53     int v;
     54     int tot;
     55     node*s[2],*f;
     56     int code;
     57     void update(){ tot = s[0]->tot + s[1]->tot +1; }
     58     
     59 };
     60 node*nt;
     61 int ncnt=10000;
     62 node*newnode(node*f,int v,int c)
     63 {
     64     if(ncnt==10000) { ncnt=0; nt=new node[10000]; }
     65     nt->f=f;
     66     nt->s[0]=nt->s[1]=nil;
     67     nt->tot=1;
     68     nt->v=v;
     69     nt->code=c;
     70     ncnt++;
     71     return nt++;
     72 }
     73 
     74 struct SplayTree
     75 {
     76     node*root;
     77     
     78     SplayTree(){ root=nil; }
     79     
     80     void rot(node*x)
     81     {
     82         node*y=x->f;
     83         if(y==nil) return ;
     84         int k=(x==y->s[0]);
     85         
     86         y->s[!k]=x->s[k];
     87         if(x->s[k]!=nil) x->s[k]->f=y;
     88         
     89         x->f=y->f;
     90         if(y==y->f->s[0]) y->f->s[0]=x;
     91         else if(y==y->f->s[1]) y->f->s[1]=x;
     92         
     93         y->f=x;
     94         x->s[k]=y;
     95         
     96         y->update();
     97     }
     98     
     99     void splay(node*x,node*t=nil)
    100     {
    101         while(x->f!=t)
    102         {
    103             node*y=x->f;
    104             if(y->f!=t)
    105             if((x==y->s[0])^(y==y->f->s[0]))
    106             rot(x); else rot(y);
    107             rot(x);
    108         }
    109         x->update();
    110         if(t==nil) root=x;
    111     }
    112     
    113     void Insert(int v,int c)
    114     { root=newnode(nil,v,c); }
    115     
    116     void Insert(node*t)
    117     {
    118         if(root==nil) 
    119         { root=t; t->s[0]=t->s[1]=t->f=nil; t->tot=1; return ; }
    120         
    121         node*x=root;
    122         node*y=nil;
    123         while(x!=nil)
    124         y=x,x=x->s[t->v>=x->v];
    125         
    126         int k=(t->v>=y->v);
    127         
    128         t->s[0]=t->s[1]=nil; t->tot=1;
    129         y->s[k]=t; t->f=y;
    130         
    131         splay(t);
    132     }
    133     
    134     node*FindRank(int k)
    135     {
    136         if(k>root->tot || k<=0) return nil;
    137         node*x=root;
    138         node*y=nil;
    139         while(x!=nil)
    140         {
    141             y=x;
    142             if(k==x->s[0]->tot+1) break;
    143             if(k>x->s[0]->tot+1)
    144             {
    145                 k-=x->s[0]->tot+1;
    146                 x=x->s[1];
    147             }
    148             else
    149                 x=x->s[0];
    150         }
    151         splay(y);
    152         return y;
    153     }
    154 };
    155 
    156 node*ary[105000]; int ac,ah;
    157 void Merge(SplayTree*&A,SplayTree*&B)
    158 {
    159     if(A->root==B->root) return ;
    160     if(A->root->tot>B->root->tot) swap(A,B);
    161     //descrete nodes of A and insert to B.
    162     ah=ac=0;
    163     ary[ac++]=A->root;
    164     while(ah!=ac)
    165     {
    166         node*x=ary[ah];
    167         if(x->s[0]!=nil) ary[ac++]=x->s[0];
    168         if(x->s[1]!=nil) ary[ac++]=x->s[1];
    169         B->Insert(x);
    170         ah++;
    171     }
    172     A=B;
    173 }
    174 
    175 SplayTree**T;
    176 
    177 int n,m,q;
    178 
    179 int main()
    180 {
    181     nil=new node;
    182     nil->f=nil->s[0]=nil->s[1]=nil;
    183     nil->tot=0;
    184     nil->code=nil->v=-2;
    185     
    186     n=getint();
    187     m=getint();
    188     
    189     T=new SplayTree*[n];
    190     for(int i=0;i<n;i++)
    191     {
    192         T[i]=new SplayTree;
    193         T[i]->Insert(getint(),i);
    194     }
    195     
    196     for(int i=0;i<m;i++)
    197     {
    198         int a=getint()-1;
    199         int b=getint()-1;
    200         if(T[a]!=T[b]) Merge(T[a],T[b]);
    201     }
    202     
    203     q=getint();
    204     for(int i=0;i<q;i++)
    205     {
    206         char c=getchar();
    207         while(c!='B' && c!='Q') c=getchar();
    208         int a=getint()-1;
    209         int b=getint()-1;
    210         if(c=='B')
    211         {
    212             if(T[a]!=T[b]) Merge(T[a],T[b]);
    213         }
    214         else if(c=='Q')
    215         {
    216             if(a<0 || a>=n) printf("%d\n",-1);
    217             else
    218             printf("%d\n",T[a]->FindRank(b+1)->code+1);
    219         }
    220     }
    221     
    222     return 0;
    223 }
    View Code

     

     

    启发式合并两棵SplayTree.

    代码好长....

    速度好慢.....

    o(╯□╰)o......

     

     


    Treap

    虽然说蛮好玩的.....

    速度快得不行....

    但是感觉代码复杂度跟splay一样啊.....

    AC BZOJ3224 普通平衡树

    排序Treap.

     

      1 #include <cstdio>
      2 #include <fstream>
      3 #include <iostream>
      4  
      5 #include <cstdlib>
      6 #include <cstring>
      7 #include <algorithm>
      8 #include <cmath>
      9  
     10 #include <queue>
     11 #include <vector>
     12 #include <map>
     13 #include <set>
     14 #include <stack>
     15 #include <list>
     16  
     17 typedef unsigned int uint;
     18 typedef long long int ll;
     19 typedef unsigned long long int ull;
     20 typedef double db;
     21  
     22 using namespace std;
     23  
     24 inline int getint()
     25 {
     26     int res=0;
     27     char c=getchar();
     28     bool mi=false;
     29     while(c<'0' || c>'9') mi=(c=='-'),c=getchar();
     30     while('0'<=c && c<='9') res=res*10+c-'0',c=getchar();
     31     return mi ? -res : res;
     32 }
     33 inline ll getll()
     34 {
     35     ll res=0;
     36     char c=getchar();
     37     bool mi=false;
     38     while(c<'0' || c>'9') mi=(c=='-'),c=getchar();
     39     while('0'<=c && c<='9') res=res*10+c-'0',c=getchar();
     40     return mi ? -res : res;
     41 }
     42  
     43 db eps=1e-80;
     44 inline bool feq(db a,db b)
     45 { return fabs(a-b)<eps; }
     46 
     47 template<typename Type>
     48 inline Type avg(const Type a,const Type b)
     49 { return a+((b-a)/2); }
     50 
     51 //===================================================================
     52 //===================================================================
     53 //===================================================================
     54 //===================================================================
     55 
     56 int INF=(1<<30)-1;
     57 
     58 int getrand()
     59 { return rand()+32768*rand(); }
     60 
     61 int t[105000];
     62 int tot[105000];
     63 int hp[105000];
     64 int s[105000][2];
     65 int f[105000];
     66 int ntot=1;
     67 
     68 int n;
     69 
     70 void update(int x)
     71 { if(x) tot[x] = tot[s[x][0]] + tot[s[x][1]] +1; }
     72 
     73 int root=0;
     74 void rot(int x)
     75 {
     76     int y=f[x];
     77     int k=(x==s[y][0]);
     78     s[y][!k]=s[x][k];
     79     if(s[x][k]) f[s[x][k]]=y;
     80     f[x]=f[y];
     81     if(y==s[f[y]][0]) s[f[y]][0]=x;
     82     else if(y==s[f[y]][1]) s[f[y]][1]=x;
     83     f[y]=x;
     84     s[x][k]=y;
     85     update(y);
     86     update(x);
     87     if(!f[x]) root=x;
     88 }
     89 
     90 int lift(int x)
     91 { while(f[x] && hp[x]<hp[f[x]]) rot(x);}
     92 
     93 void Insert(int v)
     94 {
     95     if(!root)
     96     { t[ntot]=v; tot[ntot]=1; root=ntot++; return ; }
     97     
     98     int x=root;
     99     int k=-1;
    100     while(true)
    101     {
    102         tot[x]++;
    103         if(v>t[x])
    104         {
    105             if(!s[x][1]) { k=1; break; }
    106             x=s[x][1];
    107         }
    108         else 
    109         {
    110             if(!s[x][0]) { k=0; break; }
    111             x=s[x][0];
    112         }
    113     }
    114     
    115     f[ntot]=x;
    116     tot[ntot]=1;
    117     hp[ntot]=getrand();
    118     t[ntot]=v;
    119     s[x][k]=ntot++;
    120     lift(s[x][k]);
    121 }
    122 
    123 int FindRank(int k)
    124 {
    125     int x=root;
    126     int y=0;
    127     while(x)
    128     {
    129         y=x;
    130         if(k==tot[s[x][0]]+1) break;
    131         if(k<=tot[s[x][0]])
    132         x=s[x][0];
    133         else
    134         {
    135             k-=tot[s[x][0]]+1;
    136             x=s[x][1];
    137         }
    138     }
    139     return y;
    140 }
    141 
    142 int Find(int v)
    143 {
    144     int x=root;
    145     while(true)
    146     {
    147         if(t[x]==v) return x;
    148         else x=s[x][v>=t[x]];
    149     }
    150     return -1;
    151 }
    152 
    153 int Rank(int v)
    154 {
    155     int x=root;
    156     int r=0;
    157     while(x)
    158     {
    159         if(v>t[x])
    160         {
    161             r+=tot[s[x][0]]+1;
    162             x=s[x][1];
    163         }
    164         else
    165             x=s[x][0];
    166     }
    167     return r;
    168 }
    169 
    170 void Delete(int x)
    171 {
    172     while(s[x][0] || s[x][1])
    173     {
    174         if(s[x][0]) rot(s[x][0]);
    175         else rot(s[x][1]);
    176     }
    177     
    178     if(!f[x]) root=0;
    179     else
    180     s[f[x]][x==s[f[x]][1]]=0;
    181     
    182     x=f[x];
    183     while(x) tot[x]--,x=f[x];
    184 }
    185 
    186 int Prefix(int v)
    187 {
    188     int x=root;
    189     int r=-INF;
    190     while(x)
    191     {
    192         if(t[x]<v) r=t[x]; 
    193         x=s[x][v>t[x]];
    194     }
    195     return r;
    196 }
    197 
    198 int Suffix(int v)
    199 {
    200     int x=root;
    201     int r=INF;
    202     while(x)
    203     {
    204         if(t[x]>v) r=t[x];
    205         x=s[x][v>=t[x]];
    206     }
    207     return r;
    208 }
    209 
    210 int a[105000];
    211 
    212 int main()
    213 {
    214     srand(23333);
    215     
    216     n=getint();
    217     for(int i=0;i<n;i++)
    218     {
    219         int c=getint();
    220         switch(c)
    221         {
    222             case 1: Insert(getint()); break;
    223              case 2: Delete(Find(getint())); break;
    224             case 3:  printf("%d\n",Rank(getint())+1); break;
    225             case 4:  printf("%d\n",t[FindRank(getint())]); break;
    226             case 5:  printf("%d\n",Prefix(getint())); break;
    227             default: printf("%d\n",Suffix(getint())); break;
    228         }
    229     }
    230     
    231     return 0;
    232 }
    View Code

     

     

     


    线段树

    AC BZOJ 3212 A Simple Problem 经典题

      1 #include <cstdio>
      2 #include <fstream>
      3 #include <iostream>
      4  
      5 #include <cstdlib>
      6 #include <cstring>
      7 #include <algorithm>
      8 #include <cmath>
      9  
     10 #include <queue>
     11 #include <vector>
     12 #include <map>
     13 #include <set>
     14 #include <stack>
     15 #include <list>
     16  
     17 typedef unsigned int uint;
     18 typedef long long int ll;
     19 typedef unsigned long long int ull;
     20 typedef double db;
     21  
     22 using namespace std;
     23  
     24 inline int getint()
     25 {
     26     int res=0;
     27     char c=getchar();
     28     bool mi=false;
     29     while(c<'0' || c>'9') mi=(c=='-'),c=getchar();
     30     while('0'<=c && c<='9') res=res*10+c-'0',c=getchar();
     31     return mi ? -res : res;
     32 }
     33 inline ll getll()
     34 {
     35     ll res=0;
     36     char c=getchar();
     37     bool mi=false;
     38     while(c<'0' || c>'9') mi=(c=='-'),c=getchar();
     39     while('0'<=c && c<='9') res=res*10+c-'0',c=getchar();
     40     return mi ? -res : res;
     41 }
     42 
     43 //==============================================================================
     44 //==============================================================================
     45 //==============================================================================
     46 //==============================================================================
     47 
     48 
     49 int n,m;
     50 int a[105000];
     51 ll t[405000];
     52 ll tag[405000];
     53 void Build(int x=1,int l=0,int r=n-1)
     54 {
     55     if(l==r) { t[x]=a[l]; return ; }
     56     int mid=(l+r)>>1;
     57     Build(x<<1,l,mid); Build(x<<1|1,mid+1,r);
     58     t[x]=t[x<<1]+t[x<<1|1];
     59 }
     60 int cl,cr,cv;
     61 void Change(int x=1,int l=0,int r=n-1)
     62 {
     63     if(cr<l || r<cl) return ;
     64     if(cl<=l && r<=cr) { tag[x]+=cv; return ; }
     65     int mid=(l+r)>>1;
     66     Change(x<<1,l,mid),Change(x<<1|1,mid+1,r);
     67     t[x]=t[x<<1]+tag[x<<1]*(mid-l+1)+t[x<<1|1]+tag[x<<1|1]*(r-mid);
     68 }
     69 int ql,qr;
     70 ll Query(int x=1,int l=0,int r=n-1)
     71 {
     72     if(qr<l || r<ql) return 0;
     73     if(ql<=l && r<=qr) return t[x]+tag[x]*(r-l+1);
     74     int mid=(l+r)>>1;
     75     return Query(x<<1,l,mid)+Query(x<<1|1,mid+1,r)+
     76             tag[x]*(min(r,qr)-max(l,ql)+1);
     77 }
     78 int main()
     79 {
     80     n=getint();
     81     m=getint();
     82     for(int i=0;i<n;i++)
     83     a[i]=getint();
     84     Build();
     85     for(int i=0;i<m;i++)
     86     {
     87         char c=getchar();
     88         while(c!='Q' && c!='C') c=getchar();
     89         if(c=='C')
     90         {
     91             cl=getint()-1;
     92             cr=getint()-1;
     93             cv=getint();
     94             Change();
     95         }
     96         else //if(c=='Q')
     97         {
     98             ql=getint()-1;
     99             qr=getint()-1;
    100             printf("%lld\n",Query());
    101         }
    102     }
    103     
    104     return 0;
    105 }
    View Code

    区间加,区间求和.永久性lazytag.常数大概是普通线段树的四分之一.......

     

    AC BZOJ 3685 用线段树做平衡树查询

      1 #include <cstdio>
      2 #include <fstream>
      3 #include <iostream>
      4  
      5 #include <cstdlib>
      6 #include <cstring>
      7 #include <algorithm>
      8 #include <cmath>
      9  
     10 #include <queue>
     11 #include <vector>
     12 #include <map>
     13 #include <set>
     14 #include <stack>
     15 #include <list>
     16  
     17 typedef unsigned int uint;
     18 typedef long long int ll;
     19 typedef unsigned long long int ull;
     20 typedef double db;
     21 typedef long double ldb;
     22  
     23 using namespace std;
     24  
     25 inline int getint()
     26 {
     27     int res=0;
     28     char c=getchar();
     29     bool mi=false;
     30     while((c<'0' || c>'9')/* && !feof(stdin)*/) mi=(c=='-'),c=getchar();
     31     while('0'<=c && c<='9'/* && !feof(stdin)*/) res=res*10+c-'0',c=getchar();
     32     return mi ? -res : res;
     33 }
     34 inline ll getll()
     35 {
     36     ll res=0;
     37     char c=getchar();
     38     bool mi=false;
     39     while(c<'0' || c>'9') mi=(c=='-'),c=getchar();
     40     while('0'<=c && c<='9') res=res*10+c-'0',c=getchar();
     41     return mi ? -res : res;
     42 }
     43 
     44 //==============================================================================
     45 //==============================================================================
     46 //==============================================================================
     47 //==============================================================================
     48 
     49 int n;
     50 int L,R;
     51 int t[4005000];
     52 
     53 int cp,cv;
     54 void Change(int x=1,int l=L,int r=R)
     55 {
     56     if(l==r) { t[x]=cv; return ; }
     57     int mid=(l+r)>>1;
     58     if(cp<=mid) Change(x<<1,l,mid);
     59     else Change(x<<1|1,mid+1,r);
     60     t[x]=t[x<<1]+t[x<<1|1];
     61 }
     62 
     63 int GetMin(int x=1,int l=L,int r=R)
     64 {
     65     if(!t[x]) return -1;
     66     while(l!=r)
     67     {
     68         int mid=(l+r)>>1;
     69         if(t[x<<1]) { r=mid; x<<=1; }
     70         else { l=mid+1; x=x<<1|1; }
     71     }
     72     return l;
     73 }
     74 
     75 int GetMax(int x=1,int l=L,int r=R)
     76 {
     77     if(!t[x]) return -1;
     78     while(l!=r)
     79     {
     80         int mid=(l+r)>>1;
     81         if(t[x<<1|1]) { l=mid+1; x=x<<1|1; }
     82         else { r=mid; x<<=1; }
     83     }
     84     return l;
     85 }
     86 
     87 int Exist(int p,int x=1,int l=L,int r=R)
     88 {
     89     if(!t[x]) return -1;
     90     while(l!=r)
     91     {
     92         int mid=(l+r)>>1;
     93         if(p<=mid) { x<<=1; r=mid; }
     94         else { x=x<<1|1; l=mid+1; }
     95         if(!t[x]) return -1;
     96     }
     97     return 1;
     98 }
     99 
    100 int Prefix(int v,int x=1,int l=L,int r=R)
    101 {
    102     int y=0,yl=0,yr=0;
    103     while(l!=r)
    104     {
    105         int mid=(l+r)>>1;
    106         if(v<=mid) { x<<=1; r=mid; }
    107         else 
    108         {
    109             if(t[x<<1]) { y=x<<1; yl=l; yr=mid; }
    110             x=x<<1|1; l=mid+1;
    111         }
    112     }
    113     return y ? GetMax(y,yl,yr) : -1;
    114 }
    115 
    116 int Suffix(int v,int x=1,int l=L,int r=R)
    117 {
    118     int y=0,yl=0,yr=0;
    119     while(l!=r)
    120     {
    121         int mid=(l+r)>>1;
    122         if(v<=mid)
    123         {
    124             if(t[x<<1|1]) { y=x<<1|1; yl=mid+1; yr=r; }
    125             x<<=1; r=mid;
    126         }
    127         else { x=x<<1|1; l=mid+1; }
    128     }
    129     return y ? GetMin(y,yl,yr) : -1;
    130 }
    131 
    132 int main()
    133 {
    134     n=getint();
    135     L=-1; R=n+1;
    136     int m=getint();
    137     for(int i=0;i<m;i++)
    138     {
    139         int c=getint();
    140         switch(c)
    141         {
    142             case 1: cp=getint(); cv=1; Change(); break;
    143             case 2: cp=getint(); cv=0; Change(); break;
    144             case 3: printf("%d\n",GetMin()); break;
    145             case 4: printf("%d\n",GetMax()); break;
    146             case 5: printf("%d\n",Prefix(getint())); break;
    147             case 6: printf("%d\n",Suffix(getint())); break;
    148             case 7: printf("%d\n",Exist(getint()));
    149             default:break;
    150         }
    151     }
    152     
    153     return 0;
    154 }
    View Code

    注意前驱和后继的写法:

    想象一下前缀的搜索过程,我们先搜索到询问数字的代表节点,然后回退,如果左子树非空就进入这棵左子树并一直往右往下走.

    先写一个GetMax和GetMin函数,表示找到某一棵子树中最靠右的存在的节点.

    然后查询前驱(或后继)时,考虑记下一个"最右(左)可行子树y".就是说

    我们遍历从根到所查询的值的节点的路径,如果遍历过程中往右(左)走了,并且当前节点左(右)子树非空,

    那么拿当前节点的左(右)子树替换掉y,这样我们就得到了"最靠右(左)的可行子树".

    然后在这棵子树中GetMax(GetMin)就行了.

     


    可持久化线段树

    AC VIJOS 1081 野生动物园

    一道非常裸的区间k大

     1 const int INF=(1<<30)-1;
     2 
     3 struct node
     4 {
     5     int t;
     6     node*l,*r;
     7     node(){ t=0; l=r=NULL;  }
     8     
     9     void update()
    10     { t=l->t+r->t; }
    11 }pool[4000000];
    12 int nt;
    13 node*newnode()
    14 { return &pool[nt++]; }
    15 
    16 node*nil;
    17 
    18 node*root[100050];
    19 
    20 void SegmentTreeInit(int size)
    21 {
    22     nil=newnode();
    23     nil->l=nil->r=nil;
    24     nil->t=0;
    25     for(int i=0;i<=size;i++)
    26     root[i]=nil;
    27 }
    28 
    29 int cp;
    30 node*Change(node*x,node*y,int l,int r)
    31 {
    32     if(cp<l || r<cp) return y;
    33     x=newnode();
    34     if(l==r) { x->t=1+y->t; return x; }
    35     int mid=(l+r)>>1;
    36     x->l=Change(x->l,y->l,l,mid);
    37     x->r=Change(x->r,y->r,mid+1,r);
    38     x->update();
    39     return x;
    40 }
    41 void Change(int i,int j,int pos)
    42 { cp=pos; root[i]=Change(nil,root[j],0,INF); }
    43 
    44 int Query(int ql,int qr,int k)
    45 {
    46     node*x=root[ql],*y=root[qr];
    47     int l=0,r=INF;
    48     while(l!=r)
    49     {
    50         int mid=(l+r)>>1;
    51         if( k<= x->l->t - y->l->t )
    52              r=mid,x=x->l,y=y->l;
    53         else
    54         {
    55             k-=x->l->t-y->l->t;
    56             l=mid+1,x=x->r,y=y->r;
    57         }
    58     }
    59     return l;
    60 }
    61 
    62 
    63 
    64 int n;
    65 
    66 
    67 
    68 int main()
    69 {
    70     
    71     int q;
    72     scanf("%d",&n);
    73     scanf("%d",&q);
    74     
    75     SegmentTreeInit(n);
    76     
    77     
    78     for(int i=0;i<n;i++)
    79     {
    80         int c;
    81         scanf("%d",&c);
    82         cp=c;
    83         root[i+1]=Change(root[i+1],root[i],0,INF);
    84     }
    85     
    86     
    87     for(int i=0;i<q;i++)
    88     {
    89         int a,b,k;
    90         scanf("%d%d%d",&a,&b,&k);
    91         printf("%d\n",Query(b,a-1,k));
    92     }
    93     
    94     return 0;
    95 }
    View Code

    要点1.使用nil节点可以省一点代码

    要点2.千万注意空间开销.一般为nlogv级别,数组经常开上百万(懒得写离散化系列)

    要点3.注意前缀和的写法. tree[R]-tree[L-1]. 这就要求root[0]=nil.

    要点4.智商捉急表示普通查找操作总是写错...splay也一样.....思考...思考......写之前一定要想好....

     

    AC BZOJ 3932 加强版的主席树,以时间轴为询问区间,插入一个值,删除一个值.

      1 #include <cstdio>
      2 #include <fstream>
      3 #include <iostream>
      4  
      5 #include <cstdlib>
      6 #include <cstring>
      7 #include <algorithm>
      8 #include <cmath>
      9  
     10 #include <queue>
     11 #include <vector>
     12 #include <map>
     13 #include <set>
     14 #include <stack>
     15 #include <list>
     16  
     17 typedef unsigned int uint;
     18 typedef long long int ll;
     19 typedef unsigned long long int ull;
     20 typedef double db;
     21  
     22 using namespace std;
     23  
     24 inline int getint()
     25 {
     26     int res=0;
     27     char c=getchar();
     28     bool mi=false;
     29     while(c<'0' || c>'9') mi=(c=='-'),c=getchar();
     30     while('0'<=c && c<='9') res=res*10+c-'0',c=getchar();
     31     return mi ? -res : res;
     32 }
     33 inline ll getll()
     34 {
     35     ll res=0;
     36     char c=getchar();
     37     bool mi=false;
     38     while(c<'0' || c>'9') mi=(c=='-'),c=getchar();
     39     while('0'<=c && c<='9') res=res*10+c-'0',c=getchar();
     40     return mi ? -res : res;
     41 }
     42 
     43 //==============================================================================
     44 //==============================================================================
     45 //==============================================================================
     46 //==============================================================================
     47 
     48 const int INF=10000001;
     49 
     50 struct node*nil;
     51 struct node
     52 {
     53     int t;
     54     ll v;
     55     node*l,*r;
     56     
     57     void update()
     58     { t = l->t + r->t; v = l->v + r->v; }
     59     
     60 };
     61 int cnt=10000;
     62 node*nt;
     63 node*newnode()
     64 {
     65     if(cnt==10000){ cnt=0; nt=new node[10000]; }
     66     nt->t=nt->v=0;
     67     nt->l=nt->r=nil;
     68     cnt++;
     69     return nt++;
     70 }
     71 
     72 int n,m;
     73 
     74 node*root[105000];
     75 
     76 struct operation
     77 {
     78     int p; //time block
     79     int v; //value
     80     bool type; //0:add 1:dec
     81     
     82 }op[205000];
     83 
     84 bool cmp(const operation&a,const operation&b)
     85 { return a.p<b.p; }
     86 
     87 
     88 int cp,cv;
     89 node*Change(node*y,int l,int r)
     90 {
     91     if(cp<l || r<cp) return y;
     92     node*x=newnode();
     93     if(l==r) { x->t=y->t+cv; x->v=y->v+cp*cv; return x; }
     94     int mid=(l+r)>>1;
     95     x->l=Change(y->l,l,mid);
     96     x->r=Change(y->r,mid+1,r);
     97     x->update();
     98     return x;
     99 }
    100 
    101 node*Change(int p,int v,node*pre)
    102 { cp=p; cv=v; return Change(pre,0,INF); }
    103 
    104 
    105 int ql,qr;
    106 
    107 ll rest;
    108 ll last;
    109 int Query(int k,node*x) //x-y. query for the kth node.
    110 {
    111     if(x->t<k) return INF;
    112     int l=0,r=INF;
    113     while(l!=r)
    114     {
    115         int mid=(l+r)>>1;
    116         if(k<=x->l->t)
    117         {
    118             x=x->l;
    119             r=mid;
    120         }
    121         else
    122         {
    123             k-=x->l->t;
    124             x=x->r;
    125             l=mid+1;
    126         }
    127     }
    128     rest=x->t-k;
    129     last=x->v/x->t;
    130     return l;
    131 }
    132 
    133 ll Query(node*x,int l=0,int r=INF) //x-y. query for sum.
    134 {
    135     if(qr<l || r<ql) return 0;
    136     if(ql<=l && r<=qr) return x->v;
    137     int mid=(l+r)>>1;
    138     return Query(x->l,l,mid) + Query(x->r,mid+1,r);
    139 }
    140 
    141 int main()
    142 {
    143     nil=newnode();
    144     nil->l=nil->r=nil;
    145     
    146     n=getint();
    147     m=getint();
    148     for(int i=0;i<n;i++)
    149     {
    150         int a=getint();
    151         int b=getint();
    152         int c=getint();
    153         op[i].p=a; op[i].v=c; op[i].type=0;
    154         op[i+n].p=b+1; op[i+n].v=c; op[i+n].type=1;
    155     }
    156     
    157     for(int i=0;i<=103000;i++) root[i]=nil;
    158     
    159     sort(op,op+2*n,cmp);
    160 
    161     int cur=0;
    162     for(int i=1;i<=103000;i++)
    163     {
    164         root[i]=root[i-1];
    165         while(op[cur].p==i && cur<2*n)
    166         {
    167             root[i]=Change(op[cur].v,op[cur].type==0 ? 1 : -1,root[i]);
    168             cur++;
    169         }
    170     }
    171     
    172     ll pre=1;
    173     
    174     ql=0;
    175     for(int i=0;i<m;i++)
    176     {
    177         int p=getint();
    178         int a=getint();
    179         int b=getint();
    180         int c=getint();
    181         ll k=((ll)a*pre+(ll)b)%c+1;
    182         qr=Query(k,root[p]);
    183         printf("%lld\n",pre=(Query(root[p])-rest*last));
    184     }
    185     
    186     
    187     return 0;
    188 }
    View Code

    所以说啊....我写的可持久化线段树也没那么容易RE啊.....COT怎么就是A不了呢.....

    WA了一发是因为没有想清楚前k个的含义,那些值与第k个元素相等但不计入结果的元素没有考虑进去....

    哎......这个算智商么......

     

    AC BZOJ3674 可持久化并查集加强版

      1 #include <cstdio>
      2 #include <fstream>
      3 #include <iostream>
      4  
      5 #include <cstdlib>
      6 #include <cstring>
      7 #include <algorithm>
      8 #include <cmath>
      9  
     10 #include <queue>
     11 #include <vector>
     12 #include <map>
     13 #include <set>
     14 #include <stack>
     15 #include <list>
     16  
     17 typedef unsigned int uint;
     18 typedef long long int ll;
     19 typedef unsigned long long int ull;
     20 typedef double db;
     21  
     22 using namespace std;
     23  
     24 inline int getint()
     25 {
     26     int res=0;
     27     char c=getchar();
     28     bool mi=false;
     29     while(c<'0' || c>'9') mi=(c=='-'),c=getchar();
     30     while('0'<=c && c<='9') res=res*10+c-'0',c=getchar();
     31     return mi ? -res : res;
     32 }
     33 inline ll getll()
     34 {
     35     ll res=0;
     36     char c=getchar();
     37     bool mi=false;
     38     while(c<'0' || c>'9') mi=(c=='-'),c=getchar();
     39     while('0'<=c && c<='9') res=res*10+c-'0',c=getchar();
     40     return mi ? -res : res;
     41 }
     42 
     43 //==============================================================================
     44 //==============================================================================
     45 //==============================================================================
     46 //==============================================================================
     47 
     48 
     49 struct node*nil;
     50 struct node
     51 {
     52     int v;
     53     node*l,*r;
     54 };
     55 int ncnt=4000;
     56 node*nt;
     57 node*newnode()
     58 {
     59     if(ncnt==4000) { ncnt=0; nt=new node[4000]; }
     60     nt->v=0;
     61     nt->l=nt->r=nil;
     62     ncnt++;
     63     return nt++;
     64 }
     65 
     66 node*root[405000]; //operations.
     67 
     68 int n,m;
     69 
     70 int cp,cv;
     71 node*Change(node*y,int l=0,int r=n+1)
     72 {
     73     if(cp<l || r<cp) return y;
     74     node*x=newnode();
     75     if(l==r) { x->v=cv; return x; }
     76     int mid=(l+r)>>1;
     77     x->l=Change(y->l,l,mid);
     78     x->r=Change(y->r,mid+1,r);
     79     return x;
     80 }
     81 
     82 int Get(node*x,int p)
     83 {
     84     int l=0,r=n+1;
     85     while(l!=r)
     86     {
     87         int mid=(l+r)>>1;
     88         if(p<=mid)
     89         x=x->l,r=mid;
     90         else
     91         x=x->r,l=mid+1;
     92     }
     93     return x->v;
     94 }
     95 
     96 node*Build(int l=0,int r=n+1)
     97 {
     98     node*x=newnode();
     99     if(l==r) { x->v=l; return x; }
    100     int mid=(l+r)>>1;
    101     x->l=Build(l,mid);
    102     x->r=Build(mid+1,r);
    103     return x;
    104 }
    105 
    106 int findf(node*&t,int x)
    107 {
    108     int f=Get(t,x);
    109     if(f==x) return x;
    110     int ff=findf(t,f);
    111     cp=x; cv=ff;
    112     t=Change(t);
    113     return ff;
    114 }
    115 
    116 int main()
    117 {
    118     nil=newnode();
    119     nil->v=0;
    120     nil->l=nil->r=nil;
    121     
    122     n=getint();
    123     m=getint();
    124     
    125     root[0]=Build();
    126     
    127     int lastans=0;
    128     
    129     for(int i=1;i<=m;i++)
    130     {
    131         int c=getint();
    132         
    133         if(c==1) //Merge
    134         {
    135             int a=getint();
    136             int b=getint();
    137             
    138             root[i]=root[i-1];
    139             int fa=findf(root[i],a);
    140             int fb=findf(root[i],b);
    141             if(fa!=fb)
    142             {
    143                 cp=fa;
    144                 cv=fb;
    145                 root[i]=Change(root[i]);
    146             }
    147         }
    148         else if(c==2) //Back
    149         {
    150             int k=getint()^lastans;
    151             root[i]=root[k];
    152         }
    153         else if(c==3) //Query
    154         {
    155             int a=getint()^lastans;
    156             int b=getint()^lastans;
    157             root[i]=root[i-1];
    158             int fa=findf(root[i],a);
    159             int fb=findf(root[i],b);
    160             printf("%d\n",lastans=(fa==fb));
    161         }
    162     }
    163     
    164     return 0;
    165 }
    View Code

    好吧,不知怎么的就A了.....

    加强版的话,不加路径压缩会TLE哦.....

     

    AC BZOJ2588 SPOJ:COT Count On A Tree

      1 #include <cstdio>
      2 #include <fstream>
      3 #include <iostream>
      4  
      5 #include <cstdlib>
      6 #include <cstring>
      7 #include <algorithm>
      8 #include <cmath>
      9  
     10 #include <queue>
     11 #include <vector>
     12 #include <map>
     13 #include <set>
     14 #include <stack>
     15 #include <list>
     16  
     17 typedef unsigned int uint;
     18 typedef long long int ll;
     19 typedef unsigned long long int ull;
     20 typedef double db;
     21 typedef long double ldb;
     22  
     23 using namespace std;
     24  
     25 inline int getint()
     26 {
     27     int res=0;
     28     char c=getchar();
     29     bool mi=false;
     30     while(c<'0' || c>'9') mi=(c=='-'),c=getchar();
     31     while('0'<=c && c<='9') res=res*10+c-'0',c=getchar();
     32     return mi ? -res : res;
     33 }
     34 inline ll getll()
     35 {
     36     ll res=0;
     37     char c=getchar();
     38     bool mi=false;
     39     while(c<'0' || c>'9') mi=(c=='-'),c=getchar();
     40     while('0'<=c && c<='9') res=res*10+c-'0',c=getchar();
     41     return mi ? -res : res;
     42 }
     43 
     44 //==============================================================================
     45 //==============================================================================
     46 //==============================================================================
     47 //==============================================================================
     48 
     49 struct edge
     50 { int in; edge*nxt; };
     51 int ecnt=2000; edge*et;
     52 edge*eds[105000];
     53 void addedge(int a,int b)
     54 {
     55     if(ecnt==2000) { ecnt=0; et=new edge[2000]; }
     56     et->in=b; et->nxt=eds[a]; eds[a]=et++; ecnt++;
     57 }
     58 #define FOREACH_EDGE(e,x) for(edge*e=eds[x];e;e=e->nxt)
     59 
     60 int v[105000]; int lim=0;
     61 
     62 struct node*nil;
     63 struct node
     64 { int t; node*l,*r; void update(){t=l->t+r->t;} };
     65 int ncnt=4000; node*nt;
     66 node*newnode()
     67 {
     68     if(ncnt==4000) { ncnt=0; nt=new node[4000]; }
     69     ncnt++; return nt++;
     70 }
     71 int cp;
     72 node*Insert(node*y,int l=0,int r=lim-1)
     73 {
     74     node*x=newnode();
     75     if(l==r) { x->l=x->r=nil; x->t=y->t+1; return x; }
     76     int mid=(l+r)>>1;
     77     x->l= cp<=mid ? Insert(y->l,l,mid) : y->l;
     78     x->r= cp>mid ? Insert(y->r,mid+1,r) : y->r;
     79     x->update(); return x;
     80 }
     81 
     82 int n,m,q;
     83 
     84 int a[105000];
     85 int dep[105000];
     86 int f[105000];
     87 node*root[105000];
     88 int ch[105000]; int chtot=0;
     89 int h[105000];
     90 
     91 int Build(int x)
     92 {
     93     //printf("%d\n",x);
     94     int sum=0;
     95     int mxp=0;
     96     int mx=0;
     97     FOREACH_EDGE(e,x)
     98     if(e->in!=f[x]) 
     99     {
    100         dep[e->in]=dep[x]+1;
    101         f[e->in]=x;
    102         cp=a[e->in]; root[e->in]=Insert(root[x]);
    103         int v=Build(e->in);
    104         if(v>mx) mx=v,mxp=e->in;
    105         sum+=v;
    106     }
    107     
    108     if(mxp) ch[x]=ch[mxp];
    109     else ch[x]=chtot++;
    110     h[ch[x]]=x;
    111     
    112     return sum+1;
    113 }
    114 
    115 int getlca(int a,int b)
    116 {
    117     while(ch[a]!=ch[b])
    118     {
    119         if(dep[h[ch[a]]]<dep[h[ch[b]]]) swap(a,b);
    120         a=f[h[ch[a]]];
    121     }
    122     return dep[a]<dep[b] ? a : b;
    123 }
    124 
    125 int Query(int a,int b,int k)
    126 {
    127     node*c[4];
    128     c[0]=root[a];
    129     c[1]=root[b];
    130     int lca=getlca(a,b);
    131     c[2]=root[lca];
    132     c[3]=root[f[lca]];
    133     int l=0,r=lim-1;
    134     while(l!=r)
    135     {
    136         int mid=(l+r)>>1;
    137         int lv=c[0]->l->t + c[1]->l->t - c[2]->l->t -c[3]->l->t;
    138         if(k<=lv)
    139         {
    140             for(int i=0;i<4;i++) c[i]=c[i]->l;
    141             r=mid;
    142         }
    143         else
    144         { 
    145             k-=lv;
    146             for(int i=0;i<4;i++) c[i]=c[i]->r;
    147             l=mid+1;
    148         }
    149     }
    150     return l;
    151 }
    152 
    153 int main()
    154 {
    155     nil=new node;
    156     nil->t=0;
    157     nil->l=nil->r=nil;
    158     
    159     n=getint();
    160     m=n-1;
    161     q=getint();
    162     for(int i=0;i<n;i++) v[i]=a[i]=getint();
    163     sort(v,v+n);
    164     lim=int(unique(v,v+n)-v);
    165     for(int i=0;i<n;i++)
    166     a[i]=int(lower_bound(v,v+lim,a[i])-v);
    167     
    168     for(int i=0;i<m;i++)
    169     {
    170         int a=getint()-1;
    171         int b=getint()-1;
    172         addedge(a,b); addedge(b,a);
    173     }
    174     addedge(n,0); //node n is a sepcial dummy node.
    175     root[n]=nil; f[n]=n;
    176     Build(n);
    177     
    178     int lst=0;
    179     for(int i=0;i<q;i++)
    180     {
    181         int a=getint();
    182         int b=getint()-1;
    183         int k=getint();
    184         a=a^lst;
    185         a--;
    186         printf("%d",lst=v[Query(a,b,k)]);
    187         if(i!=q-1) printf("\n"); 
    188     }
    189     
    190     return 0;
    191 }
    View Code

    终于A了啊.....

    离散化 + HLD-LCA 拿到了rank3 2333333

     

     


    树套树

    AC VIJOS 1665

    树状数组 套 动态开点的权值线段树

    题目就是裸的带修改区间K大

    写了一个多小时...调了大概....一个半小时?

    树状数组怎么写都快忘记了........

    由于懒得离散化......所以.....开了一个巨大的数组.......

    VJ的内存限制不错....先把数组从400W改到800W...还是RE..怒而改到1.3kW...AC了.....

    看了看空间消耗.....160M.....

    这告诉我们千万不要忽视离散化的力量!  千万不要忽视常数空间!

    但是我还是很懒=w=能不写离散化就不写离散化=w=

    好吧......

    下面是代码.....

    附带一大版的文件头以及调试信息2333

     

      1 #include <cstdio>
      2 #include <fstream>
      3 #include <iostream>
      4  
      5 #include <cstdlib>
      6 #include <cstring>
      7 #include <algorithm>
      8 #include <cmath>
      9  
     10 #include <queue>
     11 #include <vector>
     12 #include <map>
     13 #include <set>
     14 #include <stack>
     15 #include <list>
     16  
     17 typedef unsigned int uint;
     18 typedef long long int ll;
     19 typedef unsigned long long int ull;
     20 typedef double db;
     21  
     22 using namespace std;
     23  
     24 inline int getint()
     25 {
     26     int res=0;
     27     char c=getchar();
     28     bool mi=false;
     29     while(c<'0' || c>'9') mi=(c=='-'),c=getchar();
     30     while('0'<=c && c<='9') res=res*10+c-'0',c=getchar();
     31     return mi ? -res : res;
     32 }
     33 inline ll getll()
     34 {
     35     ll res=0;
     36     char c=getchar();
     37     bool mi=false;
     38     while(c<'0' || c>'9') mi=(c=='-'),c=getchar();
     39     while('0'<=c && c<='9') res=res*10+c-'0',c=getchar();
     40     return mi ? -res : res;
     41 }
     42  
     43 db eps=1e-18;
     44 inline bool feq(db a,db b)
     45 { return fabs(a-b)<eps; }
     46 
     47 inline int avg(const int a,const int b)
     48 { return a+((b-a)>>1); }
     49 
     50 //==============================================================================
     51 //==============================================================================
     52 //==============================================================================
     53 //==============================================================================
     54 
     55 const int INF=(1<<30)-1;
     56 
     57 int n;
     58 struct node*nil;
     59 struct node
     60 {
     61     int v; //total
     62     node*l,*r;
     63     void update()
     64     { v=l->v+r->v; }
     65 }pool[13000000];
     66 node*nt=pool;
     67 node*newnode()
     68 {
     69     nt->l=nt->r=nil;
     70     nt->v=0;
     71     return nt++;
     72 }
     73 
     74 int cp,cv;
     75 
     76 //Sub segment trees
     77 struct SegmentTree
     78 {
     79     node*root;
     80     
     81     node*Change(node*x,int l=0,int r=INF)
     82     {
     83         if(cp<l || r<cp) return x;
     84         if(x==nil) x=newnode();
     85         if(l==r) { x->v+=cv; return x; }
     86         int mid=avg(l,r);
     87         x->l=Change(x->l,l,mid);
     88         x->r=Change(x->r,mid+1,r);
     89         x->update();
     90         return x;
     91     }
     92     
     93     void Set(int p,int v)
     94     {
     95         if(root<pool) root=nil;
     96         cp=p;
     97         cv=v;
     98         root=Change(root);
     99     }
    100 };
    101 
    102 //original segment tree
    103 //performed as tree array
    104 
    105 #define bt(x) (x&-x)
    106 
    107 int a[1000000]; //this array must be stay here....
    108 SegmentTree t[1000000];
    109 void Change(int p,int s,int v) //location of point, value of point, delete or add in.
    110 { for(int i=p;i<=n;i+=bt(i)) t[i].Set(s,v); }
    111 
    112 node*c[1000];
    113 int adt,ct;
    114 
    115 int Query(int l,int r,int k) //find the element which is rank k.
    116 {
    117     adt=0;
    118     
    119     for(int i=r;i>0;i-=bt(i))
    120     c[adt++]=t[i].root;
    121     
    122     ct=adt;
    123     for(int i=l-1;i>0;i-=bt(i))
    124     c[ct++]=t[i].root;
    125     
    126     //we perform add when i<adt, and than dec when adt<=i<ct
    127     
    128     
    129     l=0,r=INF;
    130     while(l!=r)
    131     {
    132         //for(int i=0;i<ct;i++)
    133         //cout<<c[i]<<' '; cout<<endl; cout<<l<<' '<<r<<endl; cout<<endl;
    134     
    135         int mid=avg(l,r);
    136         int clv=0; //current node's left node count.
    137         
    138         for(int i=0;i<adt;i++)
    139         clv+=c[i]->l->v;
    140         for(int i=adt;i<ct;i++)
    141         clv-=c[i]->l->v;
    142         
    143         if(k<=clv) //the element we want find is on the left block
    144         {
    145             for(int i=0;i<ct;i++)
    146                 c[i]=c[i]->l;
    147             r=mid;
    148         }
    149         else
    150         {
    151             for(int i=0;i<ct;i++)
    152                 c[i]=c[i]->r;
    153             k-=clv;
    154             l=mid+1;
    155         }
    156     }
    157     
    158     return l;
    159 }
    160 
    161 int q;
    162 
    163 int main()
    164 {
    165     nil=newnode();
    166     nil->l=nil->r=nil;
    167     nil->v=0;
    168     
    169     n=getint();
    170     q=getint();
    171     for(int i=0;i<n;i++)
    172     Change(i+1,a[i+1]=getint(),1);
    173     
    174     for(int i=0;i<q;i++)
    175     {
    176         char c[5];
    177         scanf("%s",c);
    178         if(c[0]=='C')
    179         {
    180             int i=getint();
    181             int v=getint();
    182             Change(i,a[i],-1);
    183             Change(i,a[i]=v,1);
    184         }
    185         else
    186         {
    187             int i=getint();
    188             int j=getint();
    189             int k=getint();
    190             printf("%d\n",Query(i,j,k));
    191         }
    192     }
    193     
    194     return 0;
    195 }
    196 
    197  
    View Code

     

    需要注意的地方:

    1.树状数组什么的一级结构别写错了啊啊啊啊啊啊

    2.既然是动态开点(即便离散化了也给我动态!绝对不要写静态的树套在另外的树里面!)....

    那么,我们只需要记录每棵树的根节点就好了.其它节点在访问的时候会碰到.

    3.嗯....(结构相同的)线段树是可加的.......所以不要再去写二分,直接在加起来的那棵树上隐式二分即可.详见代码.可以降低一个log的复杂度.

    4.二分的界,以及二分后的操作(k-=...)一定要考虑清楚.

    2015年3月4日更新

    <5.不知道为什么, 用@iwtwiioi在某些地方的AC代码交到VJ,TLE了...就AC了我第一次提交没有RE的那两个范围较小的点...... http://www.cnblogs.com/iwtwiioi/p/3929957.html>

    嘛,以上TLE的原因是在BZOJ上原题的数据范围是n<=1W,VIJOS上是N<=5W.....噗......不知道当时看走眼了还是什么的囧

     

    树状数组套动态开点的权值线段树

    AC BZOJ 3196 tyvj 二逼平衡树

    传说中都用树状数组套Treap.....然而我是蒟蒻不会套平衡树......所以写了线段树.....1A.....

      1 #include <cstdio>
      2 #include <fstream>
      3 #include <iostream>
      4  
      5 #include <cstdlib>
      6 #include <cstring>
      7 #include <algorithm>
      8 #include <cmath>
      9  
     10 #include <queue>
     11 #include <vector>
     12 #include <map>
     13 #include <set>
     14 #include <stack>
     15 #include <list>
     16  
     17 typedef unsigned int uint;
     18 typedef long long int ll;
     19 typedef unsigned long long int ull;
     20 typedef double db;
     21  
     22 using namespace std;
     23  
     24 inline int getint()
     25 {
     26     int res=0;
     27     char c=getchar();
     28     bool mi=false;
     29     while(c<'0' || c>'9') mi=(c=='-'),c=getchar();
     30     while('0'<=c && c<='9') res=res*10+c-'0',c=getchar();
     31     return mi ? -res : res;
     32 }
     33 inline ll getll()
     34 {
     35     ll res=0;
     36     char c=getchar();
     37     bool mi=false;
     38     while(c<'0' || c>'9') mi=(c=='-'),c=getchar();
     39     while('0'<=c && c<='9') res=res*10+c-'0',c=getchar();
     40     return mi ? -res : res;
     41 }
     42 
     43 //==============================================================================
     44 //==============================================================================
     45 //==============================================================================
     46 //==============================================================================
     47 
     48 
     49 
     50 const int INF=100000001;
     51 
     52 
     53 struct node*nil;
     54 struct node
     55 {
     56     int v;
     57     node*l,*r;
     58 };
     59 int ncnt=5000;
     60 node*nt;
     61 node*newnode()
     62 {
     63     if(ncnt==5000) { ncnt=0; nt=new node[5000]; }
     64     nt->l=nt->r=nil;
     65     ncnt++; return nt++;
     66 }
     67 
     68 int ip,iv;
     69 void Insert(node*&x,int l=-1,int r=INF)
     70 {
     71     if(ip<l || r<ip) return ;
     72     if(x==nil) x=newnode();
     73     int mid=(l+r)>>1;
     74     if(l==r) { x->v+=iv; return ; }
     75     Insert(x->l,l,mid);
     76     Insert(x->r,mid+1,r);
     77     x->v = x->l->v + x->r->v;
     78 }
     79 
     80 int n,m;
     81 int a[50050]; // true array
     82 
     83 node*t[50050];
     84 void Change(int loc,int p,int v)
     85 {
     86     ip=p; iv=v;
     87     for(int i=loc;i<=n;i+=(i&-i))
     88     Insert(t[i]);
     89 }
     90 
     91 node*p[1000];
     92 node*s[1000];
     93 int sp,ss;
     94 inline void QueryBIT(int L,int R)
     95 {
     96     sp=ss=0;
     97     for(int i=L-1;i;i-=(i&-i)) s[ss++]=t[i];
     98     for(int i=R;i;i-=(i&-i)) p[sp++]=t[i];
     99 }
    100 inline void GoLeft()
    101 {
    102     for(int i=0;i<sp;i++) p[i]=p[i]->l;
    103     for(int i=0;i<ss;i++) s[i]=s[i]->l;
    104 }
    105 inline void GoRight()
    106 {
    107     for(int i=0;i<sp;i++) p[i]=p[i]->r;
    108     for(int i=0;i<ss;i++) s[i]=s[i]->r;
    109 }
    110 inline int CountLeft()
    111 {
    112     int res=0;
    113     for(int i=0;i<sp;i++) res+=p[i]->l->v;
    114     for(int i=0;i<ss;i++) res-=s[i]->l->v;
    115     return res;
    116 }
    117 inline int CountRight()
    118 {
    119     int res=0;
    120     for(int i=0;i<sp;i++) res+=p[i]->r->v;
    121     for(int i=0;i<ss;i++) res-=s[i]->r->v;
    122     return res;
    123 }
    124 
    125 int GetRank(int v) //Query the count of numbers smaller than v.
    126 {
    127     int l=-1,r=INF;
    128     int res=0;
    129     while(l!=r)
    130     {
    131         int mid=(l+r)>>1;
    132         if(v<=mid) { GoLeft(); r=mid; }
    133         else { res+=CountLeft(); GoRight(); l=mid+1; }
    134     }
    135     return res;
    136 }
    137 
    138 int FindRank(int k) //find the number with rank k.
    139 {
    140     int l=-1,r=INF;
    141     while(l!=r)
    142     {
    143         int mid=(l+r)>>1;
    144         int t=CountLeft();
    145         if(k<=t) { GoLeft(); r=mid; }
    146         else { k-=t; GoRight(); l=mid+1; }
    147     }
    148     return l;
    149 }
    150 
    151 int GetPrefix(int L,int R,int v)
    152 {
    153     QueryBIT(L,R);
    154     int t=GetRank(v);
    155     QueryBIT(L,R);
    156     return FindRank(t);
    157 }
    158 
    159 int GetSuffix(int L,int R,int v)
    160 {
    161     QueryBIT(L,R);
    162     int t=GetRank(v+1);
    163     QueryBIT(L,R);
    164     return FindRank(t+1);
    165 }
    166 
    167 int main()
    168 {
    169     nil=new node;
    170     nil->l=nil->r=nil;
    171     nil->v=0;
    172     
    173     n=getint();
    174     m=getint();
    175     
    176     for(int i=0;i<=n;i++)
    177     t[i]=nil;
    178     
    179     for(int i=1;i<=n;i++)
    180     Change(i,a[i]=getint(),1);
    181     
    182     for(int i=0;i<m;i++)
    183     {
    184         int c=getint();
    185         int b=getint();
    186         int d=getint();
    187         if(c==1) //Get Rank
    188         {
    189             int v=getint();
    190             QueryBIT(b,d);
    191             printf("%d\n",GetRank(v)+1);
    192         }
    193         else if(c==2) //Find by Rank
    194         {
    195             int k=getint();
    196             QueryBIT(b,d);
    197             printf("%d\n",FindRank(k));            
    198         }
    199         else if(c==3) //Change
    200         {
    201             Change(b,a[b],-1);
    202             Change(b,a[b]=d,1);
    203         }
    204         else if(c==4) //Prefix
    205         {
    206             int v=getint();
    207             printf("%d\n",GetPrefix(b,d,v));
    208         }
    209         else if(c==5) //Suffix
    210         {
    211             int v=getint();
    212             printf("%d\n",GetSuffix(b,d,v));
    213         }
    214     }
    215     
    216     return 0;
    217 }
    View Code

    运行时间为3.46s. 这个找前驱和后继的操作简直SXBK......

    先统计一下比那个数小的数的个数(就是找排名)......然后再找到排名等于那个数的数......后继差不多.....

    似乎比较慢? 没有开离散化....内存用得很多.....但是比treap快2333333

      1 #include <cstdio>
      2 #include <fstream>
      3 #include <iostream>
      4  
      5 #include <cstdlib>
      6 #include <cstring>
      7 #include <algorithm>
      8 #include <cmath>
      9  
     10 #include <queue>
     11 #include <vector>
     12 #include <map>
     13 #include <set>
     14 #include <stack>
     15 #include <list>
     16  
     17 typedef unsigned int uint;
     18 typedef long long int ll;
     19 typedef unsigned long long int ull;
     20 typedef double db;
     21  
     22 using namespace std;
     23  
     24 inline int getint()
     25 {
     26     int res=0;
     27     char c=getchar();
     28     bool mi=false;
     29     while(c<'0' || c>'9') mi=(c=='-'),c=getchar();
     30     while('0'<=c && c<='9') res=res*10+c-'0',c=getchar();
     31     return mi ? -res : res;
     32 }
     33 inline ll getll()
     34 {
     35     ll res=0;
     36     char c=getchar();
     37     bool mi=false;
     38     while(c<'0' || c>'9') mi=(c=='-'),c=getchar();
     39     while('0'<=c && c<='9') res=res*10+c-'0',c=getchar();
     40     return mi ? -res : res;
     41 }
     42 
     43 //==============================================================================
     44 //==============================================================================
     45 //==============================================================================
     46 //==============================================================================
     47 
     48 
     49 struct node*nil;
     50 struct node
     51 {
     52     int v;
     53     node*l,*r;
     54 };
     55 int ncnt=5000;
     56 node*nt;
     57 node*newnode()
     58 {
     59     if(ncnt==5000) { ncnt=0; nt=new node[5000]; }
     60     nt->l=nt->r=nil;
     61     ncnt++; return nt++;
     62 }
     63 
     64 int lim;
     65 
     66 int ip,iv;
     67 void Insert(node*&x,int l=0,int r=lim-1)
     68 {
     69     if(ip<l || r<ip) return ;
     70     if(x==nil) x=newnode();
     71     int mid=(l+r)>>1;
     72     if(l==r) { x->v+=iv; return ; }
     73     Insert(x->l,l,mid);
     74     Insert(x->r,mid+1,r);
     75     x->v = x->l->v + x->r->v;
     76 }
     77 
     78 int n,m;
     79 int a[50050]; // true array
     80 
     81 node*t[50050];
     82 void Change(int loc,int p,int v)
     83 {
     84     ip=p; iv=v;
     85     for(int i=loc;i<=n;i+=(i&-i))
     86     Insert(t[i]);
     87 }
     88 
     89 node*p[1000];
     90 node*s[1000];
     91 int sp,ss;
     92 inline void QueryBIT(int L,int R)
     93 {
     94     sp=ss=0;
     95     for(int i=L-1;i;i-=(i&-i)) s[ss++]=t[i];
     96     for(int i=R;i;i-=(i&-i)) p[sp++]=t[i];
     97 }
     98 inline void GoLeft()
     99 {
    100     for(int i=0;i<sp;i++) p[i]=p[i]->l;
    101     for(int i=0;i<ss;i++) s[i]=s[i]->l;
    102 }
    103 inline void GoRight()
    104 {
    105     for(int i=0;i<sp;i++) p[i]=p[i]->r;
    106     for(int i=0;i<ss;i++) s[i]=s[i]->r;
    107 }
    108 inline int CountLeft()
    109 {
    110     int res=0;
    111     for(int i=0;i<sp;i++) res+=p[i]->l->v;
    112     for(int i=0;i<ss;i++) res-=s[i]->l->v;
    113     return res;
    114 }
    115 inline int CountRight()
    116 {
    117     int res=0;
    118     for(int i=0;i<sp;i++) res+=p[i]->r->v;
    119     for(int i=0;i<ss;i++) res-=s[i]->r->v;
    120     return res;
    121 }
    122 
    123 int GetRank(int v) //Query the count of numbers smaller than v.
    124 {
    125     int l=0,r=lim-1;
    126     int res=0;
    127     while(l!=r)
    128     {
    129         int mid=(l+r)>>1;
    130         if(v<=mid) { GoLeft(); r=mid; }
    131         else { res+=CountLeft(); GoRight(); l=mid+1; }
    132     }
    133     return res;
    134 }
    135 
    136 int FindRank(int k) //find the number with rank k.
    137 {
    138     int l=0,r=lim-1;
    139     while(l!=r)
    140     {
    141         int mid=(l+r)>>1;
    142         int t=CountLeft();
    143         if(k<=t) { GoLeft(); r=mid; }
    144         else { k-=t; GoRight(); l=mid+1; }
    145     }
    146     return l;
    147 }
    148 
    149 int GetPrefix(int L,int R,int v)
    150 {
    151     QueryBIT(L,R);
    152     int t=GetRank(v);
    153     QueryBIT(L,R);
    154     return FindRank(t);
    155 }
    156 
    157 int GetSuffix(int L,int R,int v)
    158 {
    159     QueryBIT(L,R);
    160     int t=GetRank(v+1);
    161     QueryBIT(L,R);
    162     return FindRank(t+1);
    163 }
    164 
    165 int op[50050][4];
    166 int v[105000];
    167 int c;
    168 
    169 int main()
    170 {
    171     nil=new node;
    172     nil->l=nil->r=nil;
    173     nil->v=0;
    174     
    175     n=getint();
    176     m=getint();
    177     
    178     for(int i=0;i<=n;i++)
    179     t[i]=nil;
    180     
    181     for(int i=1;i<=n;i++)
    182     v[c++]=a[i]=getint();
    183     
    184     for(int i=0;i<m;i++)
    185     {
    186         op[i][0]=getint();
    187         op[i][1]=getint();
    188         op[i][2]=getint();
    189         if(op[i][0]!=3) op[i][3]=getint();
    190         
    191         if(op[i][0]==3) v[c++]=op[i][2];
    192         else
    193         if(op[i][0]!=2) v[c++]=op[i][3];
    194     }
    195     
    196     sort(v,v+c);
    197     lim=int(unique(v,v+c)-v);
    198     for(int i=1;i<=n;i++)
    199     a[i]=int(lower_bound(v,v+lim,a[i])-v);
    200     for(int i=0;i<m;i++)
    201     if(op[i][0]==3) op[i][2]=int(lower_bound(v,v+lim,op[i][2])-v);
    202     else
    203     if(op[i][0]!=2) op[i][3]=int(lower_bound(v,v+lim,op[i][3])-v);
    204     
    205     for(int i=1;i<=n;i++)
    206     Change(i,a[i],1);
    207     
    208     for(int i=0;i<m;i++)
    209     {
    210         //printf("i:%d ",i);
    211         if(op[i][0]==1) //Get Rank
    212         {
    213             QueryBIT(op[i][1],op[i][2]);
    214             printf("%d\n",GetRank(op[i][3])+1);
    215         }
    216         else if(op[i][0]==2) //Find by Rank
    217         {
    218             QueryBIT(op[i][1],op[i][2]);
    219             printf("%d\n",v[FindRank(op[i][3])]);            
    220         }
    221         else if(op[i][0]==3) //Change
    222         {
    223             Change(op[i][1],a[op[i][1]],-1);
    224             Change(op[i][1],a[op[i][1]]=op[i][2],1);
    225         }
    226         else if(op[i][0]==4) //Prefix
    227             printf("%d\n",v[GetPrefix(op[i][1],op[i][2],op[i][3])]);
    228         else if(op[i][0]==5) //Suffix
    229             printf("%d\n",v[GetSuffix(op[i][1],op[i][2],op[i][3])]);
    230     }
    231     
    232     return 0;
    233 }
    View Code

    加离散化之后2.37s....内存少了50M.....

     

    AC BZOJ 3110

    权值线段树套常规线段树

      1 #include <cstdio>
      2 #include <fstream>
      3 #include <iostream>
      4 
      5 #include <cstdlib>
      6 #include <cstring>
      7 #include <algorithm>
      8 #include <cmath>
      9 
     10 #include <queue>
     11 #include <vector>
     12 #include <map>
     13 #include <set>
     14 #include <stack>
     15 #include <list>
     16 
     17 typedef unsigned int uint;
     18 typedef long long int ll;
     19 typedef unsigned long long int ull;
     20 typedef double db;
     21 typedef long double ldb;
     22 
     23 using namespace std;
     24 
     25 inline int getint()
     26 {
     27     int res=0;
     28     char c=getchar();
     29     bool mi=false;
     30     while((c<'0' || c>'9')/* && !feof(stdin)*/) mi=(c=='-'),c=getchar();
     31     while('0'<=c && c<='9'/* && !feof(stdin)*/) res=res*10+c-'0',c=getchar();
     32     return mi ? -res : res;
     33 }
     34 inline ll getll()
     35 {
     36     ll res=0;
     37     char c=getchar();
     38     bool mi=false;
     39     while(c<'0' || c>'9') mi=(c=='-'),c=getchar();
     40     while('0'<=c && c<='9') res=res*10+c-'0',c=getchar();
     41     return mi ? -res : res;
     42 }
     43 
     44 //==============================================================================
     45 //==============================================================================
     46 //==============================================================================
     47 //==============================================================================
     48 
     49 
     50 struct operation{bool t; int l,r; int v; }op[50050];
     51 int dsv[50050]; int vt;
     52 
     53 //segment tree
     54 struct node{ node*l,*r; int t; int tag; };
     55 node*nt; int ncnt=20000;
     56 node*newnode()
     57 {
     58     if(ncnt==20000){ nt=new node[20000]; ncnt=0; }
     59     nt->l=nt->r=NULL; nt->t=nt->tag=0; ncnt++;
     60     return nt++;
     61 }
     62 
     63 int n,m;
     64 
     65 int cl,cr;
     66 void Change(node*&x,int l=0,int r=n-1)
     67 {
     68     if(x==NULL) x=newnode();
     69     if(cl<=l && r<=cr) { x->tag++; return ; }
     70     int mid=(l+r)>>1;
     71     if(mid>=cl) Change(x->l,l,mid);
     72     if(mid<cr) Change(x->r,mid+1,r);
     73     x->t = ( x->l ? x->l->t + x->l->tag*(mid-l+1) : 0 ) + 
     74            ( x->r ? x->r->t + x->r->tag*(r-mid)   : 0 ) ;
     75 }
     76 int ql,qr;
     77 int Query(node*x,int l=0,int r=n-1)
     78 {
     79     if(qr<l || r<ql || x==NULL) return 0;
     80     if(ql<=l && r<=qr) { return x->t + x->tag*(r-l+1); }
     81     int mid=(l+r)>>1;
     82     return Query(x->l,l,mid)+Query(x->r,mid+1,r)+x->tag*(min(qr,r)-max(ql,l)+1) ;
     83 }
     84 
     85 node*t[205000]; //outer segment tree
     86 
     87 void Insert(int L,int R,int p,int x=1,int l=0,int r=vt-1)
     88 {
     89     cl=L; cr=R; 
     90     while(l!=r)
     91     {
     92         int mid=(l+r)>>1;
     93         Change(t[x]);
     94         if(p<=mid) { x<<=1; r=mid; }
     95         else { x=x<<1|1; l=mid+1; }
     96     }
     97     Change(t[x]);
     98 }
     99 
    100 int Query(int L,int R,int k,int x=1,int l=0,int r=vt-1)
    101 {
    102     ql=L; qr=R;
    103     while(l!=r)
    104     {
    105         int mid=(l+r)>>1;
    106         int v=Query(t[x<<1|1]);
    107         if(k>v) { k-=v; x<<=1; r=mid; }
    108         else { x=x<<1|1; l=mid+1; }
    109     }
    110     return l;
    111 }
    112 
    113 int main()
    114 {
    115     n=getint();
    116     m=getint();
    117     
    118     for(int i=0;i<m;i++)
    119     {
    120         op[i].t=getint()-1;
    121         op[i].l=getint()-1;
    122         op[i].r=getint()-1;
    123         op[i].v=getint();
    124         if(!op[i].t) dsv[vt++]=op[i].v;
    125     }
    126     sort(dsv,dsv+vt);
    127     vt=int(unique(dsv,dsv+vt)-dsv);
    128     for(int i=0;i<m;i++) if(!op[i].t)
    129     { op[i].v=int(lower_bound(dsv,dsv+vt,op[i].v)-dsv); }
    130     
    131     for(int i=0;i<m;i++)
    132     {
    133         if(op[i].t) printf("%d\n",dsv[Query(op[i].l,op[i].r,op[i].v)]);
    134         else Insert(op[i].l,op[i].r,op[i].v);
    135     }
    136     
    137     return 0;
    138 }
    View Code

    居然能这么玩..好神......

    我们不是要对每个询问在权值线段树上跑嘛...那么位置限制[l,r]怎么办呢? 树套树! 每一个权值线段树的节点都开一棵线段树,用于统计该节点代表的所有权值在某个区间[l,r]内出现过几次.....好神好神.....

     


    动态树

    不带其余任何标记的,带换根的LCT.

    AC BZOJ2049 一道非常裸的LCT.

      1 #include <cstdio>
      2 #include <fstream>
      3 #include <iostream>
      4  
      5 #include <cstdlib>
      6 #include <cstring>
      7 #include <algorithm>
      8 #include <cmath>
      9  
     10 #include <queue>
     11 #include <vector>
     12 #include <map>
     13 #include <set>
     14 #include <stack>
     15 #include <list>
     16  
     17 typedef unsigned int uint;
     18 typedef long long int ll;
     19 typedef unsigned long long int ull;
     20 typedef double db;
     21  
     22 using namespace std;
     23  
     24 inline int getint()
     25 {
     26     int res=0;
     27     char c=getchar();
     28     bool mi=false;
     29     while(c<'0' || c>'9') mi=(c=='-'),c=getchar();
     30     while('0'<=c && c<='9') res=res*10+c-'0',c=getchar();
     31     return mi ? -res : res;
     32 }
     33 inline ll getll()
     34 {
     35     ll res=0;
     36     char c=getchar();
     37     bool mi=false;
     38     while(c<'0' || c>'9') mi=(c=='-'),c=getchar();
     39     while('0'<=c && c<='9') res=res*10+c-'0',c=getchar();
     40     return mi ? -res : res;
     41 }
     42  
     43 db eps=1e-18;
     44 inline bool feq(db a,db b)
     45 { return fabs(a-b)<eps; }
     46 
     47 template<typename Type>
     48 inline Type avg(const Type a,const Type b)
     49 { return a+((b-a)/2); }
     50 
     51 //==============================================================================
     52 //==============================================================================
     53 //==============================================================================
     54 //==============================================================================
     55 
     56 
     57 
     58 
     59 
     60 struct node* nil;
     61 
     62 struct node
     63 {
     64     bool rev;
     65     node*s[2],*f;
     66 
     67     bool root() 
     68     { return this!=f->s[0] && this!=f->s[1]; }
     69     
     70     void pushtag()
     71     {
     72         if(rev)
     73         {
     74             s[0]->rev^=1;
     75             s[1]->rev^=1;
     76             swap(s[0],s[1]);
     77             rev=false;
     78         }
     79     }
     80     
     81 };
     82 
     83 
     84 struct LinkCutTree
     85 {
     86     node*nt;
     87     LinkCutTree(int size)
     88     {
     89         nt=new node[size];
     90         for(int i=0;i<size;i++)
     91         {
     92             nt[i].s[0]=nt[i].s[1]=nt[i].f=nil;
     93             nt[i].rev=false;
     94         }
     95     }
     96     
     97     void cleartag(node*x)
     98     { if(!x->root()) cleartag(x->f); x->pushtag(); }
     99     
    100     node*operator[](int k)
    101     { return nt+k; }
    102     
    103     void rot(node*x)
    104     {
    105         if(x->root()) return ;
    106         node*y=x->f;
    107         bool k=(x==y->s[0]);
    108         
    109         y->s[!k]=x->s[k];
    110         if(x->s[k]!=nil) x->s[k]->f=y;
    111         
    112         x->f=y->f;
    113         if(y==y->f->s[0]) y->f->s[0]=x;
    114         else if(y==y->f->s[1]) y->f->s[1]=x;
    115         
    116         y->f=x;
    117         x->s[k]=y;
    118     }
    119     
    120     void splay(node*x)
    121     {
    122         cleartag(x);
    123         while(!x->root())
    124         {
    125             node*y=x->f;
    126             if(!y->root())
    127             {
    128                 if((x==y->s[0])^(y==y->f->s[0]))
    129                 rot(y); else rot(x);
    130             }
    131             rot(x);
    132         }
    133     }
    134     
    135     node*access(node*x)
    136     {
    137         node*y=nil;
    138         node*t=x;
    139         while(t!=nil)
    140         {
    141             splay(t);
    142             t->s[0]=y;
    143             y=t;
    144             t=t->f;
    145         }
    146         splay(x);
    147         return x;
    148     }
    149     
    150     node*FindRoot(node*x)
    151     {
    152         access(x);
    153         while(x->s[1]!=nil) x=x->s[1];
    154         return x;
    155     }
    156     
    157     node*SetRoot(node*x)
    158     {
    159         access(x)->rev^=1;
    160         return x;
    161     }
    162     
    163     void Link(node*x,node*y)
    164     {
    165         SetRoot(x)->f=y;
    166     }
    167     
    168     void Cut(node*x,node*y)
    169     {
    170         SetRoot(x);
    171         access(y);
    172         y->s[1]->f=nil;
    173         y->s[1]=nil;
    174     }
    175     
    176     void output(int i)
    177     { cout<<i<<' '<<&nt[i]<<' '<<nt[i].s[0]<<' '<<nt[i].s[1]<<' '<<nt[i].f<<endl; }
    178 };
    179 
    180 int n,m;
    181 
    182 int main()
    183 {
    184     nil=new node;
    185     nil->s[0]=nil->s[1]=nil->f=nil;
    186     
    187     n=getint();
    188     m=getint();
    189     
    190     LinkCutTree t(n);
    191     
    192     for(int i=0;i<m;i++)
    193     {
    194         char c[20];
    195         scanf("%s",c);
    196         if(c[0]=='C') //Link
    197         {
    198             t.Link(t[getint()-1],t[getint()-1]);
    199         }
    200         else if(c[0]=='D') //Cut
    201         {
    202             t.Cut(t[getint()-1],t[getint()-1]);
    203         }
    204         else if(c[0]=='Q') //Query
    205         {
    206             if(t.FindRoot(t[getint()-1])==t.FindRoot(t[getint()-1])) printf("Yes\n");
    207             else printf("No\n");
    208         }
    209     }
    210     
    211     return 0;
    212 }
    View Code

     
    很奇怪,Link,Cut,FindRoot和SetRoot这些函数换一种写法就各种TLE/RE,还有cleartag()也是一样,不知道为什么.....

     

    还是LCT.

    AC VIJOS1190 LCT-MST

      1 #include <cstdio>
      2 #include <fstream>
      3 #include <iostream>
      4  
      5 #include <cstdlib>
      6 #include <cstring>
      7 #include <algorithm>
      8 #include <cmath>
      9  
     10 #include <queue>
     11 #include <vector>
     12 #include <map>
     13 #include <set>
     14 #include <stack>
     15 #include <list>
     16  
     17 typedef unsigned int uint;
     18 typedef long long int ll;
     19 typedef unsigned long long int ull;
     20 typedef double db;
     21  
     22 using namespace std;
     23  
     24 inline int getint()
     25 {
     26     int res=0;
     27     char c=getchar();
     28     bool mi=false;
     29     while(c<'0' || c>'9') mi=(c=='-'),c=getchar();
     30     while('0'<=c && c<='9') res=res*10+c-'0',c=getchar();
     31     return mi ? -res : res;
     32 }
     33 inline ll getll()
     34 {
     35     ll res=0;
     36     char c=getchar();
     37     bool mi=false;
     38     while(c<'0' || c>'9') mi=(c=='-'),c=getchar();
     39     while('0'<=c && c<='9') res=res*10+c-'0',c=getchar();
     40     return mi ? -res : res;
     41 }
     42  
     43 db eps=1e-18;
     44 inline bool feq(db a,db b)
     45 { return fabs(a-b)<eps; }
     46 
     47 template<typename Type>
     48 inline Type avg(const Type a,const Type b)
     49 { return a+((b-a)/2); }
     50 
     51 //==============================================================================
     52 //==============================================================================
     53 //==============================================================================
     54 //==============================================================================
     55 
     56 
     57 const int INF=(1<<30)-1;
     58 
     59 
     60 struct node* nil;
     61 
     62 struct node
     63 {
     64     node*mxp;
     65     int code;
     66     int v;
     67     bool rev;
     68     node*s[2],*f;
     69 
     70     bool root() 
     71     { return this!=f->s[0] && this!=f->s[1]; }
     72     
     73     void pushtag()
     74     {
     75         if(rev)
     76         {
     77             s[0]->rev^=1;
     78             s[1]->rev^=1;
     79             swap(s[0],s[1]);
     80             rev=false;
     81         }
     82     }
     83     
     84     void update()
     85     {
     86         mxp=this;
     87         int lv=s[0]->mxp->v;
     88         int rv=s[1]->mxp->v;
     89         if(lv>mxp->v) mxp=s[0]->mxp;
     90         if(rv>mxp->v) mxp=s[1]->mxp;
     91     }
     92 };
     93 
     94 
     95 struct LinkCutTree
     96 {
     97     node*nt;
     98     LinkCutTree(int size)
     99     {
    100         nt=new node[size];
    101         for(int i=0;i<size;i++)
    102         {
    103             nt[i].s[0]=nt[i].s[1]=nt[i].f=nil;
    104             nt[i].rev=false;
    105             nt[i].mxp=&nt[i];
    106             nt[i].v=-INF;
    107             nt[i].code=i;
    108         }
    109     }
    110     
    111     void cleartag(node*x)
    112     { if(!x->root()) cleartag(x->f); x->pushtag(); }
    113     
    114     node*operator[](int k)
    115     { return nt+k; }
    116     
    117     void rot(node*x)
    118     {
    119         if(x->root()) return ;
    120         node*y=x->f;
    121         bool k=(x==y->s[0]);
    122         
    123         y->s[!k]=x->s[k];
    124         if(x->s[k]!=nil) x->s[k]->f=y;
    125         
    126         x->f=y->f;
    127         if(y==y->f->s[0]) y->f->s[0]=x;
    128         else if(y==y->f->s[1]) y->f->s[1]=x;
    129         
    130         y->f=x;
    131         x->s[k]=y;
    132         
    133         y->update();
    134     }
    135     
    136     void splay(node*x)
    137     {
    138         cleartag(x);
    139         while(!x->root())
    140         {
    141             node*y=x->f;
    142             if(!y->root())
    143             {
    144                 if((x==y->s[0])^(y==y->f->s[0]))
    145                 rot(y); else rot(x);
    146             }
    147             rot(x);
    148         }
    149         x->update();
    150     }
    151     
    152     node*access(node*x)
    153     {
    154         node*y=nil;
    155         while(x!=nil)
    156         {
    157             splay(x);
    158             x->s[0]=y;
    159             y=x;
    160             x=x->f;
    161         }
    162         return x;
    163     }
    164     
    165     node*expend(node*x)
    166     {
    167         access(x);
    168         splay(x);
    169         return x;
    170     }
    171     
    172     node*FindRoot(node*x)
    173     {
    174         expend(x);
    175         while(x->s[1]!=nil) x=x->s[1];
    176         splay(x);
    177         return x;
    178     }
    179     
    180     node*SetRoot(node*x)
    181     {
    182         expend(x)->rev^=1;
    183         return x;
    184     }
    185     
    186     void Link(node*x,node*y)
    187     {
    188         SetRoot(x)->f=y;
    189     }
    190     
    191     void Cut(node*x,node*y)
    192     {
    193         SetRoot(x);
    194         expend(y);
    195         y->s[1]->f=nil;
    196         y->s[1]=nil;
    197     }
    198     
    199     node* GetMax(node*x,node*y)
    200     {
    201         SetRoot(x);
    202         return expend(y)->mxp;
    203     }
    204     
    205     
    206     void output(int i)
    207     { printf("%p[ id:%d v:%d L:%p R:%p f:%p rev:%d max:%d ]\n",&nt[i],nt[i].code,nt[i].v,nt[i].s[0],nt[i].s[1],nt[i].f,nt[i].rev,nt[i].mxp->v); }
    208 };
    209 
    210 int n,m;
    211 int EL[10050];
    212 int ER[10050];
    213 
    214 int main()
    215 {
    216     nil=new node;
    217     nil->mxp=nil->s[0]=nil->s[1]=nil->f=nil;
    218     nil->v=-INF;
    219     nil->code=-1;
    220     
    221     n=getint();
    222     m=getint();
    223     
    224     LinkCutTree T(n+m+1);
    225     
    226     int mx=-INF;
    227     
    228     for(int i=0;i<m;i++)
    229     {
    230         int p=n+i;
    231         
    232         int a,b,c;
    233         EL[i]=(a=getint()-1);
    234         ER[i]=(b=getint()-1);
    235         c=getint();
    236         
    237         T[p]->v=c;
    238         
    239         bool able=true;
    240         
    241         if(T.FindRoot(T[a])==T.FindRoot(T[b]))
    242         {
    243             node* mxp=T.GetMax(T[a],T[b]);
    244             able=false;
    245             
    246             if(mxp->v>c)
    247             {
    248                 int d=mxp->code-n;
    249                 
    250                 T.Cut(T[EL[d]],mxp);
    251                 T.Cut(T[ER[d]],mxp);
    252                 
    253                 able=true;
    254             }
    255         }
    256         
    257         if(able)
    258         {
    259             T.Link(T[a],T[p]);
    260             T.Link(T[b],T[p]);
    261         }
    262     }
    263     
    264     for(int i=n;i<n+m;i++)
    265     if(T.FindRoot(T[0])==T.FindRoot(T[i]))
    266     mx=max(mx,T[i]->v);
    267     
    268     printf("%d %d\n",n-1,mx);
    269     
    270     return 0;
    271 }
    View Code

    调半天发现update写错了......TAT

     要点:

    1.所有的操作函数都不要写错啊!虽然很短......

    2.access操作返回的是上一次access时的路径与本次access节点在有根树的LCA.

       所以用expend函数来作为返回x的access操作.

    3.找到根后别忘记splay根上去,毕竟访问了根节点就要保证其复杂度.

    4.Cut操作一定要换根,expend(y)之后,把y与y的右儿子断掉.尤其是x,y不一定相邻的时候.

    5.update()与pushtag()别写错!

    6.在splay前把要splay的节点的父节点的tag清空.因为splay操作是以结构作为基础的.

    7.不要在写LCT的时候纠结struct node到底该写哪怎么写的问题!想到怎么写就怎么写,并且LCT函数全部用node*形式.

     

    NOI2014 Day1 T2 魔法森林 用LCT维护MST.上一题就是为这个做准备的.

      1 #include <cstdio>
      2 #include <fstream>
      3 #include <iostream>
      4  
      5 #include <cstdlib>
      6 #include <cstring>
      7 #include <algorithm>
      8 #include <cmath>
      9  
     10 #include <queue>
     11 #include <vector>
     12 #include <map>
     13 #include <set>
     14 #include <stack>
     15 #include <list>
     16  
     17 typedef unsigned int uint;
     18 typedef long long int ll;
     19 typedef unsigned long long int ull;
     20 typedef double db;
     21  
     22 using namespace std;
     23  
     24 inline int getint()
     25 {
     26     int res=0;
     27     char c=getchar();
     28     bool mi=false;
     29     while(c<'0' || c>'9') mi=(c=='-'),c=getchar();
     30     while('0'<=c && c<='9') res=res*10+c-'0',c=getchar();
     31     return mi ? -res : res;
     32 }
     33 inline ll getll()
     34 {
     35     ll res=0;
     36     char c=getchar();
     37     bool mi=false;
     38     while(c<'0' || c>'9') mi=(c=='-'),c=getchar();
     39     while('0'<=c && c<='9') res=res*10+c-'0',c=getchar();
     40     return mi ? -res : res;
     41 }
     42  
     43 db eps=1e-18;
     44 inline bool feq(db a,db b)
     45 { return fabs(a-b)<eps; }
     46 
     47 template<typename Type>
     48 inline Type avg(const Type a,const Type b)
     49 { return a+((b-a)/2); }
     50 
     51 //==============================================================================
     52 //==============================================================================
     53 //==============================================================================
     54 //==============================================================================
     55 
     56 
     57 const int INF=(1<<30)-1;
     58 
     59 
     60 struct node* nil;
     61 
     62 struct node
     63 {
     64     node*mxp;
     65     int code;
     66     int v;
     67     bool rev;
     68     node*s[2],*f;
     69 
     70     bool root() 
     71     { return this!=f->s[0] && this!=f->s[1]; }
     72     
     73     void pushtag()
     74     {
     75         if(rev)
     76         {
     77             s[0]->rev^=1;
     78             s[1]->rev^=1;
     79             swap(s[0],s[1]);
     80             rev=false;
     81         }
     82     }
     83     
     84     void update()
     85     {
     86         mxp=this;
     87         int lv=s[0]->mxp->v;
     88         int rv=s[1]->mxp->v;
     89         if(lv>mxp->v) mxp=s[0]->mxp;
     90         if(rv>mxp->v) mxp=s[1]->mxp;
     91     }
     92 };
     93 
     94 
     95 struct LinkCutTree
     96 {
     97     node*nt;
     98     LinkCutTree(int size)
     99     {
    100         nt=new node[size];
    101         for(int i=0;i<size;i++)
    102         {
    103             nt[i].s[0]=nt[i].s[1]=nt[i].f=nil;
    104             nt[i].rev=false;
    105             nt[i].mxp=&nt[i];
    106             nt[i].v=-INF;
    107             nt[i].code=i;
    108         }
    109     }
    110     
    111     void cleartag(node*x)
    112     { if(!x->root()) cleartag(x->f); x->pushtag(); }
    113     
    114     node*operator[](int k)
    115     { return nt+k; }
    116     
    117     void rot(node*x)
    118     {
    119         if(x->root()) return ;
    120         node*y=x->f;
    121         bool k=(x==y->s[0]);
    122         
    123         y->s[!k]=x->s[k];
    124         if(x->s[k]!=nil) x->s[k]->f=y;
    125         
    126         x->f=y->f;
    127         if(y==y->f->s[0]) y->f->s[0]=x;
    128         else if(y==y->f->s[1]) y->f->s[1]=x;
    129         
    130         y->f=x;
    131         x->s[k]=y;
    132         
    133         y->update();
    134     }
    135     
    136     void splay(node*x)
    137     {
    138         cleartag(x);
    139         while(!x->root())
    140         {
    141             node*y=x->f;
    142             if(!y->root())
    143             {
    144                 if((x==y->s[0])^(y==y->f->s[0]))
    145                 rot(y); else rot(x);
    146             }
    147             rot(x);
    148         }
    149         x->update();
    150     }
    151     
    152     node*access(node*x)
    153     {
    154         node*y=nil;
    155         while(x!=nil)
    156         {
    157             splay(x);
    158             x->s[0]=y;
    159             y=x;
    160             x=x->f;
    161         }
    162         return x;
    163     }
    164     
    165     node*expend(node*x)
    166     {
    167         access(x);
    168         splay(x);
    169         return x;
    170     }
    171     
    172     node*FindRoot(node*x)
    173     {
    174         expend(x);
    175         while(x->s[1]!=nil) x=x->s[1];
    176         splay(x);
    177         return x;
    178     }
    179     
    180     node*SetRoot(node*x)
    181     {
    182         expend(x)->rev^=1;
    183         return x;
    184     }
    185     
    186     void Link(node*x,node*y)
    187     {
    188         SetRoot(x)->f=y;
    189     }
    190     
    191     void Cut(node*x,node*y)
    192     {
    193         SetRoot(x);
    194         expend(y);
    195         y->s[1]->f=nil;
    196         y->s[1]=nil;
    197     }
    198     
    199     node* GetMax(node*x,node*y)
    200     {
    201         SetRoot(x);
    202         return expend(y)->mxp;
    203     }
    204     
    205     
    206     void output(int i)
    207     { printf("%p[ id:%d v:%d L:%p R:%p f:%p rev:%d max:%d ]\n",&nt[i],nt[i].code,nt[i].v,nt[i].s[0],nt[i].s[1],nt[i].f,nt[i].rev,nt[i].mxp->v); }
    208 };
    209 
    210 int n,m;
    211 int EL[100050];
    212 int ER[100050];
    213 int Ea[100050];
    214 int Eb[100050];
    215 int p[100050];
    216 bool cmp(int a,int b)
    217 { return Ea[a]<Ea[b]; }
    218 
    219 int res=INF;
    220 
    221 int main()
    222 {
    223     nil=new node;
    224     nil->mxp=nil->s[0]=nil->s[1]=nil->f=nil;
    225     nil->v=-INF;
    226     nil->code=-1;
    227     
    228     n=getint();
    229     m=getint();
    230     
    231     LinkCutTree T(n+m+2);
    232     
    233     int st=0,ed=n-1;
    234     
    235     for(int i=0;i<m;i++)
    236     {
    237         EL[i]=getint()-1;
    238         ER[i]=getint()-1;
    239         Ea[i]=getint();
    240         Eb[i]=getint();
    241     }
    242     
    243     for(int i=0;i<m;i++) p[i]=i;
    244     stable_sort(p,p+m,cmp);
    245     
    246     int curbase=0;
    247     
    248     for(int i=0;i<m;i++)
    249     {
    250         int e=p[i]; //the id of current edge.
    251         int cur=n+i; //the id of current edge node.
    252         node*L=T[EL[e]];
    253         node*R=T[ER[e]];
    254         curbase=Ea[e]; //current value count.
    255         T[cur]->v=Eb[e]; //assign value of current edge node.
    256         
    257         if(L==R) continue;
    258         
    259         if(T.FindRoot(L)==T.FindRoot(R))
    260         {
    261             node*X=T.GetMax(L,R);
    262             int v=X->v;
    263             
    264             if(v>Eb[e]) //replace point mxp
    265             {
    266                 T.Cut(T[EL[X->code-n]],X);
    267                 T.Cut(T[ER[X->code-n]],X);
    268                 
    269                 T.Link(L,T[cur]);
    270                 T.Link(R,T[cur]);
    271             }
    272         }
    273         else
    274         {
    275             T.Link(L,T[cur]);
    276             T.Link(R,T[cur]);
    277         }
    278         
    279         if(T.FindRoot(T[n-1])==T.FindRoot(T[0]))
    280         {
    281             T.SetRoot(T[n-1]);
    282             T.expend(T[0]);
    283             res=min(res,curbase+T[0]->mxp->v);
    284         }
    285     }
    286     
    287     if(res==INF) printf("-1\n");
    288     else printf("%d\n",res);
    289     
    290     return 0;
    291 }
    View Code

     

     


    替罪羊树

    AC BZOJ 1588

    平衡树/权值线段树裸题.

      1 #include <cstdio>
      2 #include <fstream>
      3 #include <iostream>
      4  
      5 #include <cstdlib>
      6 #include <cstring>
      7 #include <algorithm>
      8 #include <cmath>
      9  
     10 #include <queue>
     11 #include <vector>
     12 #include <map>
     13 #include <set>
     14 #include <stack>
     15 #include <list>
     16  
     17 typedef unsigned int uint;
     18 typedef long long int ll;
     19 typedef unsigned long long int ull;
     20 typedef double db;
     21 typedef long double ldb;
     22  
     23 using namespace std;
     24  
     25 inline int getint()
     26 {
     27     int res=0;
     28     char c=getchar();
     29     bool mi=false;
     30     while((c<'0' || c>'9')&&!feof(stdin)) mi=(c=='-'),c=getchar();
     31     while(('0'<=c && c<='9')&&!feof(stdin)) res=res*10+c-'0',c=getchar();
     32     return mi ? -res : res;
     33 }
     34 inline ll getll()
     35 {
     36     ll res=0;
     37     char c=getchar();
     38     bool mi=false;
     39     while(c<'0' || c>'9') mi=(c=='-'),c=getchar();
     40     while('0'<=c && c<='9') res=res*10+c-'0',c=getchar();
     41     return mi ? -res : res;
     42 }
     43 
     44 //==============================================================================
     45 //==============================================================================
     46 //==============================================================================
     47 //==============================================================================
     48 
     49 int f[205000];
     50 int s[205000][2];
     51 int t[205000];
     52 int tot[205000];
     53 int ncnt=0;
     54 
     55 int root=0;
     56 
     57 int q[205000]; int qt;
     58 void fetch(int x)
     59 { if(!x) return ; fetch(s[x][0]); q[qt++]=x; fetch(s[x][1]); }
     60 int construct(int l=0,int r=qt-1)
     61 {
     62     if(l>r) return 0; //nil
     63     int mid=(l+r)>>1; int x=q[mid]; tot[x]=1;
     64     s[x][0]=construct(l,mid-1); f[s[x][0]]=x; tot[x]+=tot[s[x][0]];
     65     s[x][1]=construct(mid+1,r); f[s[x][1]]=x; tot[x]+=tot[s[x][1]];
     66     return x;
     67 }
     68 int rebuild(int x)
     69 { qt=0; fetch(x); return construct(); }
     70 
     71 void balance(int x)
     72 {
     73     int y=0;
     74     while(x)
     75     {
     76         if(tot[x]>=5)
     77         {
     78             db v=db(tot[s[x][0]])/db(tot[x]-1);
     79             if(v<=0.20 || v>=0.80) y=x;
     80         }
     81         x=f[x];
     82     }
     83     if(y)
     84     {
     85         int z=f[y];
     86         if(z)
     87         {
     88             int d=(y==s[z][1]);
     89             s[z][d]=rebuild(y);
     90             f[s[z][d]]=z;
     91         }
     92         else root=rebuild(y),f[root]=0;
     93     }
     94 }
     95 
     96 void Insert(int v)
     97 {
     98     int p=++ncnt; t[p]=v; tot[p]=1;
     99     if(!root) { root=p; return ; }
    100     int x=root,y=0;
    101     while(x) tot[x]+=1,y=x,x=s[x][v>=t[x]];
    102     s[y][v>=t[y]]=p; f[p]=y;
    103     balance(p);
    104 }
    105 
    106 int Rank(int v)
    107 {
    108     int x=root,res=0;
    109     while(x)
    110     if(v<=t[x]) x=s[x][0];
    111     else res+=tot[s[x][0]]+1,x=s[x][1];
    112     return res;
    113 }
    114 
    115 int FindRank(int k)
    116 {
    117     int x=root,y=0;
    118     while(x)
    119     {
    120         y=x;
    121         int c=tot[s[x][0]]+1;
    122         if(k==c) break;
    123         if(k<c) x=s[x][0];
    124         else k-=c,x=s[x][1];
    125     }
    126     return y;
    127 }
    128 
    129 int Prefix(int v) { return t[FindRank(Rank(v))]; }
    130 int Suffix(int v) { return t[FindRank(Rank(v)+1)]; }
    131 
    132 
    133 void op(int x=root)
    134 { if(!x)return; op(s[x][0]); printf("%d[v:%d l:%d r:%d f:%d tot:%d]\n",x,t[x],s[x][0],s[x][1],f[x],tot[x]); op(s[x][1]); }
    135 
    136 int n;
    137 
    138 inline int abs(int p){ return p&0x80000000 ? -p : p ; }
    139 
    140 int main()
    141 {
    142     n=getint();
    143     
    144     int res=getint(); Insert(res);
    145     for(int i=1;i<n;i++)
    146     {
    147         int c=getint();
    148         res+=min(abs(c-Prefix(c)),abs(c-Suffix(c)));
    149         Insert(c);
    150     }
    151     printf("%d\n",res);
    152     
    153     return 0;
    154 }
    View Code

    参数调成6:0.8/1,加上读入优化,跑了308ms.

    不带删除....rank查询前驱后继..........

    常数依然降不下来,晚上写一个线段树版本对比一下效率.

     ...

  • 相关阅读:
    Model, View(Camera), Perspective (1)
    流状态和c++的异常处理
    VAO VBO EBO(3)
    VAO VBO EBO(2)
    VAO VBO EBO(1)
    函数指针(2)
    函数指针
    内联函数和宏函数的一些区别
    关于宏的一些知识
    关于未来方向
  • 原文地址:https://www.cnblogs.com/DragoonKiller/p/4295945.html
Copyright © 2020-2023  润新知