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 # 定义圣诞树的绿叶函数 ...
随机推荐
- Leetcode 856. Score of Parentheses 括号得分(栈)
Leetcode 856. Score of Parentheses 括号得分(栈) 题目描述 字符串S包含平衡的括号(即左右必定匹配),使用下面的规则计算得分 () 得1分 AB 得A+B的分,比如 ...
- Git的一些用法
三. Git的一些用法 1. .gitignore文件 屏蔽文件 : .gitignore文件是告诉Git哪些目录或者文件需要忽略, 这些文件将不被提交; 常用场景 : 写完代码后会执行变异调试等操作 ...
- 将SQLAlchemy对象转化为dict
需求一,将数据对象转为dict,但是不包括relation, import BaseClass #所有模型的基础类 def getDictFromObj_nr(obj): return_dict={} ...
- linux 常用命令手册
命令 功能说明 线上查询及帮助命令(2个) man 查看命令帮助,命令的词典,更复杂的还有info,但不常用. help 查看Linux内置命令的帮助,比如cd命令. 文件和目录操作命令(18个) l ...
- Intellij idea maven 引用无法搜索远程仓库的解决方案
打开项目的POM文件,ALT+Insert键 出来添加引用的窗口 说明无法搜索到远程仓库,需要怎么设置呢? 在intellij idea 中配置好maven后 是这样的 如果加载失败,则需要自定义远程 ...
- Elasticsearch 因拷贝多余的jar到lib库导致无法启动的问题
因为需要测试,无意中拷贝了一个netty-buffer-4.1.16.Final.jar包放到es的lib目录下,晚上回家启动es的时候发现启动不起来了.检查日志发现如下错误. 其中有一句关键语句 C ...
- 论文阅读 | FPN:Feature Pyramid Networks for Object Detection
论文地址:https://arxiv.org/pdf/1612.03144v2.pdf 代码地址:https://github.com/unsky/FPN 概述 FPN是FAIR发表在CVPR 201 ...
- 自动化测试接口PYTHON
在开发测试中经常会遇到接口迭代和代码重构,一个无关紧要的改动往往会引起整个项目的运行.现有的接口测试中往往只是针对单一接口的测试,可是业务的连贯性是非常紧密的,比如:用户从登陆,获取商品信息,下单 ...
- JavaScript跨浏览器处理事件以及相关对象
主流的浏览器和IE浏览器在处理事件和事件对象上是有所区别的,我们一般会通过EventUtil进行封装,这样,就可以正常的跨浏览器处理事件了,本文的主要内容总结自<JavaScript高级程序设计 ...
- c++ 网络编程(五) LINUX下 socket编程 多种I/O函数 -以及readv和writev函数用法
原文作者:aircraft 原文链接:https://www.cnblogs.com/DOMLX/p/9614056.html 一.多种I/O函数 前言:之前我们讲的数据传输一般Linux上用writ ...