51Nod1782 圣诞树
我居然忘写题解啦!(记忆废)
总的来说这题就是道大数据结构……看我代码长度就知道了,真的是长得要死……
……
这题的操作都是路径修改单点查询,因此可以树上差分,问题就变成了维护子树中的所有标记。
注意到题目要求按照出现次数排序,可以想到用以出现次数为关键字的平衡树维护。虽然这个东西没法快速合并,但它是资瓷启发式合并的,那么我们对每个点再开一个map记录每种礼物的出现次数就好了,合并的时候同时维护平衡树和map。
合并操作只会进行$n-1$次(废话),因此复杂度为$O(n\log^2 n)$。但是这个做法常数比较大,卡常卡到死才过的……(看上去大多数人都写的平衡树启发式合并,然后这题就变成了卡常大赛……)
这份代码是卡过常的,所以比较丑,不愿看就不要勉强了……
- #include<stdio.h>
- #include<algorithm>
- #include<vector>
- #include<queue>
- #include<map>
- #define int unsigned
- #define Anti __attribute__((optimize("-Os")))
- #define Leaf __inline__ __attribute__((always_inline))
- #define dir(x) ((x)==(x)->p->ch[1])
- namespace mine{
- #define siz (1<<19)
- #define frd fread(hd=buf,1,siz,stdin)
- #define getchar() (hd==tl?(frd,*hd++):*hd++)
- char buf[siz],*hd=buf+siz,*tl=buf+siz;
- template<class T>Anti Leaf void readint(register T &__x){
- register int __c;
- __x=;
- do __c=getchar();while(__c<);
- for(;__c>;__c=getchar())__x=(__x<<)+(__x<<)+(__c^);
- }
- template<class T>Anti Leaf void writeint(T __x){
- static int __a[];
- register int __i,__j;
- __i=;
- do{
- __a[__i++]=__x%^;
- __x/=;
- }while(__x);
- for(__j=__i-;~__j;__j--)putchar(__a[__j]);
- }
- }
- using namespace mine;
- using namespace std;
- const int maxn=;
- struct node{
- int key,id,size,sum;
- node *ch[],*p;
- Anti Leaf node(register int id=,register int key=):key(key),id(id),size(),sum(id){}
- Anti Leaf int cmp(register int i,register int k){
- if(k!=key)return k>key;
- return i>id;
- }
- Anti Leaf void refresh(){
- size=ch[]->size+ch[]->size+;
- sum=ch[]->sum^ch[]->sum^id;
- }
- }*null=new node(),*root[maxn];
- struct Q{
- int k,id;
- Q(register int k,register int id):k(k),id(id){}
- };
- queue<node*>freenodes;
- void dfs1(int);
- void dfs2(int);
- int LCA(int,int);
- node *newnode(int,int);
- void delnode(node*);
- void merge(int,int);
- void insert(int,int);
- void erase(node*);
- node *kth(int,node*);
- void splay(node*,node* =null);
- void rot(node*,int);
- node *findmax(node*);
- vector<int>G[maxn];
- map<int,node*>mp[maxn];
- map<int,int>tmp[maxn];
- vector<Q>que[maxn];
- int T;
- int f[maxn][],d[maxn];
- int n,m,lgn=,ans[maxn];
- //#include<ctime>
- signed main(){
- null->size=;
- null->ch[]=null->ch[]=null->p=null;
- fill(root,root+maxn,null);
- readint(n);
- for(int i=,x,y;i<n;i++){
- readint(x);
- readint(y);
- G[x].push_back(y);
- G[y].push_back(x);
- }
- dfs1();
- for(register int j=;j<=lgn;j++)for(register int i=;i<=n;i++)f[i][j]=f[f[i][j-]][j-];
- readint(m);
- while(m--){
- int x,y,u,v;
- readint(x);
- readint(y);
- readint(v);
- readint(u);
- register int z=LCA(x,y);
- tmp[x][u]+=v;
- tmp[y][u]+=v;
- tmp[z][u]-=v;
- if(f[z][])tmp[f[z][]][u]-=v;
- }
- for(register int x=;x<=n;x++){
- T=x;
- for(map<int,int>::iterator it=tmp[x].begin();it!=tmp[x].end();it++)if(it->second){
- insert(it->first,it->second);
- mp[x][it->first]=root[x];
- }
- tmp[x].clear();
- }
- readint(m);
- for(register int i=;i<=m;i++){
- int x,k;
- readint(x);
- readint(k);
- que[x].push_back(Q(k,i));
- }
- dfs2();
- for(register int i=;i<=m;i++){
- writeint(ans[i]);
- putchar('\n');
- }
- //fprintf(fopen("con","w"),"%lf",(double)clock()/CLOCKS_PER_SEC);
- return ;
- }
- Anti void dfs1(int x){
- d[x]=d[f[x][]]+;
- while((<<lgn)<d[x])lgn++;
- for(int i=;i<(int)G[x].size();i++)if(G[x][i]!=f[x][]){
- f[G[x][i]][]=x;
- dfs1(G[x][i]);
- }
- }
- Anti void dfs2(int x){
- for(int i=;i<(int)G[x].size();i++)if(G[x][i]!=f[x][]){
- dfs2(G[x][i]);
- merge(x,G[x][i]);
- }
- T=x;
- for(int i=;i<(int)que[x].size();i++){
- if(que[x][i].k>=root[x]->size)ans[que[x][i].id]=root[x]->sum;
- else{
- splay(kth(que[x][i].k+,root[x]));
- ans[que[x][i].id]=root[x]->ch[]->sum;
- }
- }
- }
- Anti Leaf int LCA(register int x,register int y){
- if(d[x]!=d[y]){
- if(d[x]<d[y]){x^=y;y^=x;x^=y;}
- for(int i=lgn;~i;i--)if(d[f[x][i]]>=d[y])x=f[x][i];
- }
- if(x==y)return x;
- for(register int i=lgn;~i;i--)if(f[x][i]!=f[y][i]){
- x=f[x][i];
- y=f[y][i];
- }
- return f[x][];
- }
- Anti Leaf node *newnode(register int id,register int key){
- register node *x;
- if(freenodes.empty())x=new node(id,key);
- else{
- x=freenodes.front();
- freenodes.pop();
- *x=node(id,key);
- }
- x->ch[]=x->ch[]=x->p=null;
- return x;
- }
- Anti Leaf void delnode(register node *x){
- if(freenodes.size()<maxn<<)freenodes.push(x);
- else delete x;
- }
- Anti Leaf void merge(register int x,register int y){
- if(root[x]==null){
- root[x]=root[y];
- swap(mp[x],mp[y]);
- return;
- }
- else if(root[y]==null)return;
- if(root[x]->size>root[y]->size){
- register node *u=findmax(root[y]);
- T=y;splay(u);
- while(u!=null){
- if(mp[x].count(u->id)){
- register node v=*mp[x][u->id];
- T=x;erase(mp[x][u->id]);
- if(u->key+v.key){
- insert(v.id,u->key+v.key);
- mp[x][u->id]=root[x];
- }
- else mp[x].erase(u->id);
- }
- else{
- T=x;insert(u->id,u->key);
- mp[x][u->id]=root[x];
- }
- if(u->ch[]==null)break;
- T=y;
- splay(findmax(u->ch[]));
- root[y]->ch[]=null;
- delnode(u);
- u=root[y];
- }
- mp[y].clear();
- root[y]=null;
- }
- else{
- register node *u=findmax(root[x]);
- T=x;splay(u);
- while(u!=null){
- if(mp[y].count(u->id)){
- register node v=*mp[y][u->id];
- T=y;erase(mp[y][u->id]);
- if(u->key+v.key){
- insert(v.id,u->key+v.key);
- mp[y][u->id]=root[y];
- }
- else mp[y].erase(u->id);
- }
- else{
- T=y;insert(u->id,u->key);
- mp[y][u->id]=root[y];
- }
- if(u->ch[]==null)break;
- T=x;
- splay(findmax(u->ch[]));
- root[x]->ch[]=null;
- delnode(u);
- u=root[x];
- }
- mp[x].clear();
- root[x]=null;
- swap(root[x],root[y]);
- swap(mp[x],mp[y]);
- }
- }
- Anti Leaf void insert(register int id,register int key){
- if(root[T]==null){
- root[T]=newnode(id,key);
- return;
- }
- node *rt=root[T];
- register int d=;
- while(rt!=null){
- d=rt->cmp(id,key);
- if(rt->ch[d]!=null)rt=rt->ch[d];
- else{
- rt->ch[d]=newnode(id,key);
- rt->ch[d]->p=rt;
- break;
- }
- }
- for(node *y=rt;y!=null;y=y->p)y->refresh();
- splay(rt->ch[d]);
- }
- Anti Leaf void erase(register node *x){
- splay(x);
- if(x->ch[]!=null){
- splay(findmax(x->ch[]),x);
- x->ch[]->ch[]=x->ch[];
- if(x->ch[]!=null)x->ch[]->p=x->ch[];
- x->ch[]->p=null;
- root[T]=x->ch[];
- }
- else if((root[T]=x->ch[])!=null)x->ch[]->p=null;
- delnode(x);
- if(root[T]!=null)root[T]->refresh();
- }
- Anti Leaf node *kth(register int k,register node *rt){
- register int d;
- while(rt!=null){
- if(k==rt->ch[]->size+){
- splay(rt);
- return rt;
- }
- if((d=k>rt->ch[]->size))k-=rt->ch[]->size+;
- rt=rt->ch[d];
- }
- return null;
- }
- Anti Leaf node *findmax(register node *x){
- while(x->ch[]!=null)x=x->ch[];
- return x;
- }
- Anti Leaf void splay(register node *x,register node *t){
- while(x->p!=t){
- if(x->p->p==t){
- rot(x->p,dir(x)^);
- break;
- }
- if(dir(x)==dir(x->p))rot(x->p->p,dir(x->p)^);
- else rot(x->p,dir(x)^);
- rot(x->p,dir(x)^);
- }
- }
- Anti Leaf void rot(register node *x,register int d){
- register node *y=x->ch[d^];
- if((x->ch[d^]=y->ch[d])!=null)y->ch[d]->p=x;
- if((y->p=x->p)!=null)x->p->ch[dir(x)]=y;
- else root[T]=y;
- (y->ch[d]=x)->p=y;
- x->refresh();
- y->refresh();
- }
顺便说一下,用平衡树维护出现次数的想法是从我的一道原创题来的:给定一个序列,每次询问区间中出现次数第k多的数。
特此声明,版权所有……
51Nod1782 圣诞树的更多相关文章
- 利用js2image把代码压缩成圣诞树
马上圣诞节了,作为一名程序猿,如何体现自己独特的过节风格,如何在朋友圈发一张专属自己的祝福照片我觉得很有必要,你们说是不是. 谈到圣诞节,话说程序猿和圣诞之间的关系还有这么一个笑话: Q:程序员为什么 ...
- C语言 打印圣诞树
再回首<C语言编程基础>,其中不少当年老师出的题,做完后稍微做了下修改,可以输入任意行数来打印圣诞树,行数越大,树越大,当然显示器也要越大,不然就折行了. 纯粹练手跟加强记忆的东西,做个记 ...
- 用css属性画出一棵圣诞树
对于学习前端的童鞋,css的掌握是必须的.今天就来实现用css画出一棵圣诞树. 主要练习的是css里面border的练习与掌握程度. 在body创建一个主区域<div></div&g ...
- 用div画一个圣诞树
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- HTML5 Canvas圣诞树
又逢圣诞了,为了让小站NowaMagic有点节日气氛,这里也弄一棵圣诞树放放-大家可以先看下效果. 效果演示 <canvas id="c"></canvas> ...
- html5 3D圣诞树源码
1. [代码][HTML]代码 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http ...
- Turtle-可视化界面画圣诞树
圣诞节(Christmas)又称耶诞节.耶稣诞辰,译名为“基督弥撒”,是西方传统节日,起源于基督教,在每年公历12月25日.弥撒是教会的一种礼拜仪式.圣诞节是一个宗教节,因为把它当作耶稣的诞辰来庆祝, ...
- Python画一棵漂亮的樱花树(不同种樱花+玫瑰+圣诞树喔)
不少用Python(大多是turtle库)绘制的树图,感觉很漂亮,我整理了一下,挑了一些我觉得不错的代码分享给大家(这些我都测试过,确实可以生成喔~)one 樱花树 动态生成樱花效果图(这个是动态的) ...
- 使用python画一颗圣诞树
# -*- coding: utf-8 -*- # @Time : 18-12-26 上午9:32 # @Author : Felix Wang import turtle # 定义圣诞树的绿叶函数 ...
随机推荐
- Review notes
- mysql基本用法
mysql的基本用法 一.创建数据库 create database day02 default character set utf8; -- 创建表 create table user( i ...
- 4G和有线网络的自动切换
最近项目有个需求,把移动服务器设备(Ubuntu14.04)安装4G模块,但如果连接有线时,可以自动切换到有线,以降低移动流量带来的费用. 以下是我实现的方法(经过一番痛苦的摸索) 1. 脚本/opt ...
- 初学 spring
1.spring 开发环境,包含eclipse https://spring.io/tools3/sts/all/
- win7 64位英文版 ado驱动
https://www.microsoft.com/zh-tw/download/details.aspx?id=5793
- MCD的正确格式
[[99NN/etWLLP/33qnzb/eMNf5mwlh9hUsT+FYsTIU15REWiQd99vwIyZqDUDIRtvsgCP0BXDlvHJlbDR+NPhyL50wS2ThIiEwD/ ...
- hibernate 自动创建表中文乱码问题
<property name="connection.url" > <![CDATA[jdbc:mysql:///test?useUnicode=true& ...
- Robot Framework(AutoItLibrary库操作计算器)
操作计算器的例子 我们以 Windows 自带的计算器的为例,来使用 AutoItLibrary 库.创建 AutoIt 测试用例,在运行测试用例 1.定位计算器中的一些按钮的ClassnameNN ...
- Apache和Tomcat的整合过程(转载)
一 Apache与Tomcat比较联系 apache支持静态页,tomcat支持动态的,比如servlet等. 一般使用apache+tomcat的话,apache只是作为一个转发,对jsp的处理是由 ...
- KOA 与 CO 实现浅析
KOA 与 CO 的实现都非常的短小精悍,只需要花费很短的时间就可以将源代码通读一遍.以下是一些浅要的分析. 如何用 node 实现一个 web 服务器 既然 KOA 实现了 web 服务器,那我们就 ...