传送门

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

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

……

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

注意到题目要求按照出现次数排序,可以想到用以出现次数为关键字的平衡树维护。虽然这个东西没法快速合并,但它是资瓷启发式合并的,那么我们对每个点再开一个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=;
  18. do __c=getchar();while(__c<);
  19. for(;__c>;__c=getchar())__x=(__x<<)+(__x<<)+(__c^);
  20. }
  21. template<class T>Anti Leaf void writeint(T __x){
  22. static int __a[];
  23. register int __i,__j;
  24. __i=;
  25. do{
  26. __a[__i++]=__x%^;
  27. __x/=;
  28. }while(__x);
  29. for(__j=__i-;~__j;__j--)putchar(__a[__j]);
  30. }
  31. }
  32. using namespace mine;
  33. using namespace std;
  34. const int maxn=;
  35. struct node{
  36. int key,id,size,sum;
  37. node *ch[],*p;
  38. Anti Leaf node(register int id=,register int key=):key(key),id(id),size(),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[]->size+ch[]->size+;
  45. sum=ch[]->sum^ch[]->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][],d[maxn];
  71. int n,m,lgn=,ans[maxn];
  72. //#include<ctime>
  73. signed main(){
  74. null->size=;
  75. null->ch[]=null->ch[]=null->p=null;
  76. fill(root,root+maxn,null);
  77. readint(n);
  78. for(int i=,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();
  85. for(register int j=;j<=lgn;j++)for(register int i=;i<=n;i++)f[i][j]=f[f[i][j-]][j-];
  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][])tmp[f[z][]][u]-=v;
  98. }
  99. for(register int x=;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=;i<=m;i++){
  109. int x,k;
  110. readint(x);
  111. readint(k);
  112. que[x].push_back(Q(k,i));
  113. }
  114. dfs2();
  115. for(register int i=;i<=m;i++){
  116. writeint(ans[i]);
  117. putchar('\n');
  118. }
  119. //fprintf(fopen("con","w"),"%lf",(double)clock()/CLOCKS_PER_SEC);
  120. return ;
  121. }
  122. Anti void dfs1(int x){
  123. d[x]=d[f[x][]]+;
  124. while((<<lgn)<d[x])lgn++;
  125. for(int i=;i<(int)G[x].size();i++)if(G[x][i]!=f[x][]){
  126. f[G[x][i]][]=x;
  127. dfs1(G[x][i]);
  128. }
  129. }
  130. Anti void dfs2(int x){
  131. for(int i=;i<(int)G[x].size();i++)if(G[x][i]!=f[x][]){
  132. dfs2(G[x][i]);
  133. merge(x,G[x][i]);
  134. }
  135. T=x;
  136. for(int i=;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+,root[x]));
  140. ans[que[x][i].id]=root[x]->ch[]->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][];
  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[]=x->ch[]=x->p=null;
  165. return x;
  166. }
  167. Anti Leaf void delnode(register node *x){
  168. if(freenodes.size()<maxn<<)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[]==null)break;
  196. T=y;
  197. splay(findmax(u->ch[]));
  198. root[y]->ch[]=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[]==null)break;
  223. T=x;
  224. splay(findmax(u->ch[]));
  225. root[x]->ch[]=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=;
  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[]!=null){
  257. splay(findmax(x->ch[]),x);
  258. x->ch[]->ch[]=x->ch[];
  259. if(x->ch[]!=null)x->ch[]->p=x->ch[];
  260. x->ch[]->p=null;
  261. root[T]=x->ch[];
  262. }
  263. else if((root[T]=x->ch[])!=null)x->ch[]->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[]->size+){
  271. splay(rt);
  272. return rt;
  273. }
  274. if((d=k>rt->ch[]->size))k-=rt->ch[]->size+;
  275. rt=rt->ch[d];
  276. }
  277. return null;
  278. }
  279. Anti Leaf node *findmax(register node *x){
  280. while(x->ch[]!=null)x=x->ch[];
  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)^);
  287. break;
  288. }
  289. if(dir(x)==dir(x->p))rot(x->p->p,dir(x->p)^);
  290. else rot(x->p,dir(x)^);
  291. rot(x->p,dir(x)^);
  292. }
  293. }
  294. Anti Leaf void rot(register node *x,register int d){
  295. register node *y=x->ch[d^];
  296. if((x->ch[d^]=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多的数。

特此声明,版权所有……

51Nod1782 圣诞树的更多相关文章

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

    马上圣诞节了,作为一名程序猿,如何体现自己独特的过节风格,如何在朋友圈发一张专属自己的祝福照片我觉得很有必要,你们说是不是. 谈到圣诞节,话说程序猿和圣诞之间的关系还有这么一个笑话: Q:程序员为什么 ...

  2. C语言 打印圣诞树

    再回首<C语言编程基础>,其中不少当年老师出的题,做完后稍微做了下修改,可以输入任意行数来打印圣诞树,行数越大,树越大,当然显示器也要越大,不然就折行了. 纯粹练手跟加强记忆的东西,做个记 ...

  3. 用css属性画出一棵圣诞树

    对于学习前端的童鞋,css的掌握是必须的.今天就来实现用css画出一棵圣诞树. 主要练习的是css里面border的练习与掌握程度. 在body创建一个主区域<div></div&g ...

  4. 用div画一个圣诞树

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  5. HTML5 Canvas圣诞树

    又逢圣诞了,为了让小站NowaMagic有点节日气氛,这里也弄一棵圣诞树放放-大家可以先看下效果. 效果演示 <canvas id="c"></canvas> ...

  6. html5 3D圣诞树源码

    1. [代码][HTML]代码   <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http ...

  7. Turtle-可视化界面画圣诞树

    圣诞节(Christmas)又称耶诞节.耶稣诞辰,译名为“基督弥撒”,是西方传统节日,起源于基督教,在每年公历12月25日.弥撒是教会的一种礼拜仪式.圣诞节是一个宗教节,因为把它当作耶稣的诞辰来庆祝, ...

  8. Python画一棵漂亮的樱花树(不同种樱花+玫瑰+圣诞树喔)

    不少用Python(大多是turtle库)绘制的树图,感觉很漂亮,我整理了一下,挑了一些我觉得不错的代码分享给大家(这些我都测试过,确实可以生成喔~)one 樱花树 动态生成樱花效果图(这个是动态的) ...

  9. 使用python画一颗圣诞树

    # -*- coding: utf-8 -*- # @Time : 18-12-26 上午9:32 # @Author : Felix Wang import turtle # 定义圣诞树的绿叶函数 ...

随机推荐

  1. Review notes

  2. mysql基本用法

    mysql的基本用法     一.创建数据库 create database day02 default character set utf8; -- 创建表 create table user( i ...

  3. 4G和有线网络的自动切换

    最近项目有个需求,把移动服务器设备(Ubuntu14.04)安装4G模块,但如果连接有线时,可以自动切换到有线,以降低移动流量带来的费用. 以下是我实现的方法(经过一番痛苦的摸索) 1. 脚本/opt ...

  4. 初学 spring

    1.spring 开发环境,包含eclipse https://spring.io/tools3/sts/all/

  5. win7 64位英文版 ado驱动

    https://www.microsoft.com/zh-tw/download/details.aspx?id=5793

  6. MCD的正确格式

    [[99NN/etWLLP/33qnzb/eMNf5mwlh9hUsT+FYsTIU15REWiQd99vwIyZqDUDIRtvsgCP0BXDlvHJlbDR+NPhyL50wS2ThIiEwD/ ...

  7. hibernate 自动创建表中文乱码问题

    <property name="connection.url" > <![CDATA[jdbc:mysql:///test?useUnicode=true& ...

  8. Robot Framework(AutoItLibrary库操作计算器)

    操作计算器的例子 我们以 Windows 自带的计算器的为例,来使用 AutoItLibrary 库.创建 AutoIt 测试用例,在运行测试用例 1.定位计算器中的一些按钮的ClassnameNN ...

  9. Apache和Tomcat的整合过程(转载)

    一 Apache与Tomcat比较联系 apache支持静态页,tomcat支持动态的,比如servlet等. 一般使用apache+tomcat的话,apache只是作为一个转发,对jsp的处理是由 ...

  10. KOA 与 CO 实现浅析

    KOA 与 CO 的实现都非常的短小精悍,只需要花费很短的时间就可以将源代码通读一遍.以下是一些浅要的分析. 如何用 node 实现一个 web 服务器 既然 KOA 实现了 web 服务器,那我们就 ...