51Nod1782 圣诞树

传送门

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

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

……

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

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

合并操作只会进行$n-1$次(废话),因此复杂度为$O(n\log^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(‘\n‘);
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 }

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

特此声明,版权所有……

时间: 2024-08-02 06:57:36

51Nod1782 圣诞树的相关文章

python小游戏之圣诞树

圣诞期间,看了下python的for循环.刚好实践一下,一时兴起,就写了个圣诞树的小程序.供诸君一乐! 下面附上代码: #coding:utf-8 import sys def christmas(h):         print '\033[1;36;40m\t欢迎光临!\n正在为你制作专属于您的圣诞树,请稍等!\033[0m'         print '\033[1;32;40m'        # print '\t',             for i in range(1,h+

html 7 圣诞树 浮动 相对位置

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"> <head> <meta h

利用js2image把代码压缩成圣诞树

马上圣诞节了,作为一名程序猿,如何体现自己独特的过节风格,如何在朋友圈发一张专属自己的祝福照片我觉得很有必要,你们说是不是. 谈到圣诞节,话说程序猿和圣诞之间的关系还有这么一个笑话: Q:程序员为什么总是将万圣节和圣诞节弄混? A:因为oct 31==Dec 25! .... .... .... 停停停... 先不笑,咱们先冷静下... 面对圣诞节还得加班加点的苦逼程序猿们,我们来缓解下自己沉闷的心情,发挥下自己独特的艺术细胞,是时候装一下逼了... 那就让我们用手头的IDE工具来展示一颗圣诞树

汇编圣诞树

汇编版圣诞树 先附上截图: 汇编代码如下: 1 dseg segment 2 x_label dw ? ;每层空格数 3 y_label dw ? ;每层高度 4 axis equ 30 5 dseg ends 6 cseg segment 7 assume cs:cseg , ds:dseg 8 start: 9 mov ah , 0 ;设置图形显示模式4 10 mov al , 04h 11 int 10h 12 13 mov al , 04 ;color 14 15 mov dx , 60

html5 3D圣诞树源码

1. [代码][HTML]代码   <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd"><html>    <head>    <title>圣诞节圣诞树</title>    <meta charset="utf-8" > 

Css画圣诞树

今天看到一道有趣的css题,要求用html和css实现一个圣诞树(上面一个小三角,下面一个大三角,最下面是一个矩形)? 你看到后脑子中的印象是什么呢,三角形的做法,还是什么,接下来看看我的制作过程. <!DOCTYPE html> <html> <head> <title>TODO supply a title</title> <meta charset="UTF-8"> <meta name="v

如何用C语言画一个圣诞树?

我使用了左右镜像的Sierpinski triangle,每层减去上方一小块,再用符号点缀.可生成不同层数的「圣诞树」,如下图是5层的结果. #include <stdio.h> #include <stdlib.h> int main(int argc, char* argv[]) { int n = argc > 1 ? atoi(argv[1]) : 4; for (int j = 1; j <= n; j++) { int s = 1 << j, k

HTML5 Canvas圣诞树

又逢圣诞了,为了让小站NowaMagic有点节日气氛,这里也弄一棵圣诞树放放-大家可以先看下效果. 效果演示 <canvas id="c"></canvas> <script type="text/javascript"> var b = document.body; var c = document.getElementsByTagName('canvas')[0]; var a = c.getContext('2d'); do

【计蒜客习题】圣诞树

问题描述 圣诞节快到了,蒜头君准备做一棵大圣诞树.这棵树被表示成一组被编号的结点和一些边的集合,树的结点从 1 到 n 编号,树的根永远是 1.每个结点都有一个自身特有的数值,称为它的权重,各个结点的权重可能不同.对于一棵做完的树来说,每条边都有一个价值 ve,若设这条边 e 连接结点 i 和结点 j,且 i 为 j的父结点(根是最老的祖先),则该边的价值ve=sj*we,sj表示结点 j 的所有子孙及它自己的权重之和,we表示边 e 的权值.现在蒜头君想造一棵树,他有 m 条边可以选择,使得树