zoukankan      html  css  js  c++  java
  • 51Nod1782 圣诞树

    传送门

    我居然忘写题解啦!(记忆废)

    总的来说这题就是道大数据结构……看我代码长度就知道了,真的是长得要死……

    ……

    这题的操作都是路径修改单点查询,因此可以树上差分,问题就变成了维护子树中的所有标记。

    注意到题目要求按照出现次数排序,可以想到用以出现次数为关键字的平衡树维护。虽然这个东西没法快速合并,但它是资瓷启发式合并的,那么我们对每个点再开一个map记录每种礼物的出现次数就好了,合并的时候同时维护平衡树和map。

    合并操作只会进行$n-1$次(废话),因此复杂度为$O(nlog^2 n)$。但是这个做法常数比较大,卡常卡到死才过的……(看上去大多数人都写的平衡树启发式合并,然后这题就变成了卡常大赛……)

    这份代码是卡过常的,所以比较丑,不愿看就不要勉强了……

      1 #include<stdio.h>
      2 #include<algorithm>
      3 #include<vector>
      4 #include<queue>
      5 #include<map>
      6 #define int unsigned
      7 #define Anti __attribute__((optimize("-Os")))
      8 #define Leaf __inline__ __attribute__((always_inline))
      9 #define dir(x) ((x)==(x)->p->ch[1])
     10 namespace mine{
     11     #define siz (1<<19)
     12     #define frd fread(hd=buf,1,siz,stdin)
     13     #define getchar() (hd==tl?(frd,*hd++):*hd++)
     14     char buf[siz],*hd=buf+siz,*tl=buf+siz;
     15     template<class T>Anti Leaf void readint(register T &__x){
     16         register int __c;
     17         __x=0;
     18         do __c=getchar();while(__c<48);
     19         for(;__c>47;__c=getchar())__x=(__x<<1)+(__x<<3)+(__c^48);
     20     }
     21     template<class T>Anti Leaf void writeint(T __x){
     22         static int __a[25];
     23         register int __i,__j;
     24         __i=0;
     25         do{
     26             __a[__i++]=__x%10^48;
     27             __x/=10;
     28         }while(__x);
     29         for(__j=__i-1;~__j;__j--)putchar(__a[__j]);
     30     }
     31 }
     32 using namespace mine;
     33 using namespace std;
     34 const int maxn=100005;
     35 struct node{
     36     int key,id,size,sum;
     37     node *ch[2],*p;
     38     Anti Leaf node(register int id=0,register int key=0):key(key),id(id),size(1),sum(id){}
     39     Anti Leaf int cmp(register int i,register int k){
     40         if(k!=key)return k>key;
     41         return i>id;
     42     }
     43     Anti Leaf void refresh(){
     44         size=ch[0]->size+ch[1]->size+1;
     45         sum=ch[0]->sum^ch[1]->sum^id;
     46     }
     47 }*null=new node(),*root[maxn];
     48 struct Q{
     49     int k,id;
     50     Q(register int k,register int id):k(k),id(id){}
     51 };
     52 queue<node*>freenodes;
     53 void dfs1(int);
     54 void dfs2(int);
     55 int LCA(int,int);
     56 node *newnode(int,int);
     57 void delnode(node*);
     58 void merge(int,int);
     59 void insert(int,int);
     60 void erase(node*);
     61 node *kth(int,node*);
     62 void splay(node*,node* =null);
     63 void rot(node*,int);
     64 node *findmax(node*);
     65 vector<int>G[maxn];
     66 map<int,node*>mp[maxn];
     67 map<int,int>tmp[maxn];
     68 vector<Q>que[maxn];
     69 int T;
     70 int f[maxn][18],d[maxn];
     71 int n,m,lgn=0,ans[maxn];
     72 //#include<ctime>
     73 signed main(){
     74     null->size=0;
     75     null->ch[0]=null->ch[1]=null->p=null;
     76     fill(root,root+maxn,null);
     77     readint(n);
     78     for(int i=1,x,y;i<n;i++){
     79         readint(x);
     80         readint(y);
     81         G[x].push_back(y);
     82         G[y].push_back(x);
     83     }
     84     dfs1(1);
     85     for(register int j=1;j<=lgn;j++)for(register int i=1;i<=n;i++)f[i][j]=f[f[i][j-1]][j-1];
     86     readint(m);
     87     while(m--){
     88         int x,y,u,v;
     89         readint(x);
     90         readint(y);
     91         readint(v);
     92         readint(u);
     93         register int z=LCA(x,y);
     94         tmp[x][u]+=v;
     95         tmp[y][u]+=v;
     96         tmp[z][u]-=v;
     97         if(f[z][0])tmp[f[z][0]][u]-=v;
     98     }
     99     for(register int x=1;x<=n;x++){
    100         T=x;
    101         for(map<int,int>::iterator it=tmp[x].begin();it!=tmp[x].end();it++)if(it->second){
    102             insert(it->first,it->second);
    103             mp[x][it->first]=root[x];
    104         }
    105         tmp[x].clear();
    106     }
    107     readint(m);
    108     for(register int i=1;i<=m;i++){
    109         int x,k;
    110         readint(x);
    111         readint(k);
    112         que[x].push_back(Q(k,i));
    113     }
    114     dfs2(1);
    115     for(register int i=1;i<=m;i++){
    116         writeint(ans[i]);
    117         putchar('
    ');
    118     }
    119     //fprintf(fopen("con","w"),"%lf",(double)clock()/CLOCKS_PER_SEC);
    120     return 0;
    121 }
    122 Anti void dfs1(int x){
    123     d[x]=d[f[x][0]]+1;
    124     while((1<<lgn)<d[x])lgn++;
    125     for(int i=0;i<(int)G[x].size();i++)if(G[x][i]!=f[x][0]){
    126         f[G[x][i]][0]=x;
    127         dfs1(G[x][i]);
    128     }
    129 }
    130 Anti void dfs2(int x){
    131     for(int i=0;i<(int)G[x].size();i++)if(G[x][i]!=f[x][0]){
    132         dfs2(G[x][i]);
    133         merge(x,G[x][i]);
    134     }
    135     T=x;
    136     for(int i=0;i<(int)que[x].size();i++){
    137         if(que[x][i].k>=root[x]->size)ans[que[x][i].id]=root[x]->sum;
    138         else{
    139             splay(kth(que[x][i].k+1,root[x]));
    140             ans[que[x][i].id]=root[x]->ch[0]->sum;
    141         }
    142     }
    143 }
    144 Anti Leaf int LCA(register int x,register int y){
    145     if(d[x]!=d[y]){
    146         if(d[x]<d[y]){x^=y;y^=x;x^=y;}
    147         for(int i=lgn;~i;i--)if(d[f[x][i]]>=d[y])x=f[x][i];
    148     }
    149     if(x==y)return x;
    150     for(register int i=lgn;~i;i--)if(f[x][i]!=f[y][i]){
    151         x=f[x][i];
    152         y=f[y][i];
    153     }
    154     return f[x][0];
    155 }
    156 Anti Leaf node *newnode(register int id,register int key){
    157     register node *x;
    158     if(freenodes.empty())x=new node(id,key);
    159     else{
    160         x=freenodes.front();
    161         freenodes.pop();
    162         *x=node(id,key);
    163     }
    164     x->ch[0]=x->ch[1]=x->p=null;
    165     return x;
    166 }
    167 Anti Leaf void delnode(register node *x){
    168     if(freenodes.size()<maxn<<2)freenodes.push(x);
    169     else delete x;
    170 }
    171 Anti Leaf void merge(register int x,register int y){
    172     if(root[x]==null){
    173         root[x]=root[y];
    174         swap(mp[x],mp[y]);
    175         return;
    176     }
    177     else if(root[y]==null)return;
    178     if(root[x]->size>root[y]->size){
    179         register node *u=findmax(root[y]);
    180         T=y;splay(u);
    181         while(u!=null){
    182             if(mp[x].count(u->id)){
    183                 register node v=*mp[x][u->id];
    184                 T=x;erase(mp[x][u->id]);
    185                 if(u->key+v.key){
    186                     insert(v.id,u->key+v.key);
    187                     mp[x][u->id]=root[x];
    188                 }
    189                 else mp[x].erase(u->id);
    190             }
    191             else{
    192                 T=x;insert(u->id,u->key);
    193                 mp[x][u->id]=root[x];
    194             }
    195             if(u->ch[0]==null)break;
    196             T=y;
    197             splay(findmax(u->ch[0]));
    198             root[y]->ch[1]=null;
    199             delnode(u);
    200             u=root[y];
    201         }
    202         mp[y].clear();
    203         root[y]=null;
    204     }
    205     else{
    206         register node *u=findmax(root[x]);
    207         T=x;splay(u);
    208         while(u!=null){
    209             if(mp[y].count(u->id)){
    210                 register node v=*mp[y][u->id];
    211                 T=y;erase(mp[y][u->id]);
    212                 if(u->key+v.key){
    213                     insert(v.id,u->key+v.key);
    214                     mp[y][u->id]=root[y];
    215                 }
    216                 else mp[y].erase(u->id);
    217             }
    218             else{
    219                 T=y;insert(u->id,u->key);
    220                 mp[y][u->id]=root[y];
    221             }
    222             if(u->ch[0]==null)break;
    223             T=x;
    224             splay(findmax(u->ch[0]));
    225             root[x]->ch[1]=null;
    226             delnode(u);
    227             u=root[x];
    228         }
    229         mp[x].clear();
    230         root[x]=null;
    231         swap(root[x],root[y]);
    232         swap(mp[x],mp[y]);
    233     }
    234 }
    235 Anti Leaf void insert(register int id,register int key){
    236     if(root[T]==null){
    237         root[T]=newnode(id,key);
    238         return;
    239     }
    240     node *rt=root[T];
    241     register int d=0;
    242     while(rt!=null){
    243         d=rt->cmp(id,key);
    244         if(rt->ch[d]!=null)rt=rt->ch[d]; 
    245         else{
    246             rt->ch[d]=newnode(id,key);
    247             rt->ch[d]->p=rt;
    248             break;
    249         }
    250     }
    251     for(node *y=rt;y!=null;y=y->p)y->refresh();
    252     splay(rt->ch[d]);
    253 }
    254 Anti Leaf void erase(register node *x){
    255     splay(x);
    256     if(x->ch[0]!=null){
    257         splay(findmax(x->ch[0]),x);
    258         x->ch[0]->ch[1]=x->ch[1];
    259         if(x->ch[1]!=null)x->ch[1]->p=x->ch[0];
    260         x->ch[0]->p=null;
    261         root[T]=x->ch[0];
    262     }
    263     else if((root[T]=x->ch[1])!=null)x->ch[1]->p=null;
    264     delnode(x);
    265     if(root[T]!=null)root[T]->refresh();
    266 }
    267 Anti Leaf node *kth(register int k,register node *rt){
    268     register int d;
    269     while(rt!=null){
    270         if(k==rt->ch[0]->size+1){
    271             splay(rt);
    272             return rt;
    273         }
    274         if((d=k>rt->ch[0]->size))k-=rt->ch[0]->size+1;
    275         rt=rt->ch[d];
    276     }
    277     return null;
    278 }
    279 Anti Leaf node *findmax(register node *x){
    280     while(x->ch[1]!=null)x=x->ch[1];
    281     return x;
    282 }
    283 Anti Leaf void splay(register node *x,register node *t){
    284     while(x->p!=t){
    285         if(x->p->p==t){
    286             rot(x->p,dir(x)^1);
    287             break;
    288         }
    289         if(dir(x)==dir(x->p))rot(x->p->p,dir(x->p)^1);
    290         else rot(x->p,dir(x)^1);
    291         rot(x->p,dir(x)^1);
    292     }
    293 }
    294 Anti Leaf void rot(register node *x,register int d){
    295     register node *y=x->ch[d^1];
    296     if((x->ch[d^1]=y->ch[d])!=null)y->ch[d]->p=x;
    297     if((y->p=x->p)!=null)x->p->ch[dir(x)]=y;
    298     else root[T]=y;
    299     (y->ch[d]=x)->p=y;
    300     x->refresh();
    301     y->refresh();
    302 }
    View Code

    顺便说一下,用平衡树维护出现次数的想法是从我的一道原创题来的:给定一个序列,每次询问区间中出现次数第k多的数。

    特此声明,版权所有……

  • 相关阅读:
    2019/10/9 CSP-S 模拟测
    简单的面向对象
    魔术变量
    函数
    全局变量
    超级全局变量
    for循环
    while循环
    php数组排序
    python打造XslGenerator
  • 原文地址:https://www.cnblogs.com/hzoier/p/6556794.html
Copyright © 2011-2022 走看看