最近沉迷码农题无法自拔

首先有一个暴力的想法:对于每个重链维护一个splay,需要翻转的连起来,翻转,接回去

然后发现这样没问题。。。

一条链只能跨log个重链,也就只有log个splay的子树参与重排,所以一次翻转只要log^2的时间

需要维护的东西有点多

头一次在splay上维护这么多乱七八糟的东西,写错了好几遍

感觉学到不少debug技巧,也纠正了之前splay写法的一个小漏洞

话说极限数据好像和miaom拍不过啊。。。但是我们都A了啊

好烦啊不知道谁出锅了

 #include <bits/stdc++.h>
#define num(x) (dep[x]-dep[top[x]]+1)
#define ans tr[split(num(x),num(y))]
#define rt root[RT]
#define RT1 root[n+1]
#define NO 800000
#define N 800000
#define INF 2000000000
#define ll long long
using namespace std;
struct trnode
{
int size,min,max;ll sum;int plus,num;
bool rev;
trnode()
{
size=;min=max=sum=plus=rev=num=;
}
} tr[NO];
int n,m,R,p,q,RT,x,y,z,RET,E,NODE,sttop,inv_x,inv_y;ll ret;
int c[NO][],fa[NO];bool die[N];
int root[N],Fa[N],size[N],fir[N],top[N],dep[N],st[N],sz[N],lin[N];
int nex[*N],to[*N];
char cmd[];
void up(int x)
{
if(!x)
{
tr[]=trnode();tr[].size=;
return;
}
tr[x].size=tr[c[x][]].size+tr[c[x][]].size+;
tr[x].sum=tr[c[x][]].sum+tr[c[x][]].sum+(ll)tr[x].plus*tr[x].size+tr[x].num;
tr[x].max=max(tr[c[x][]].max,tr[c[x][]].max)+tr[x].plus;
tr[x].max=max(tr[x].max,tr[x].num+tr[x].plus);
tr[x].min=tr[x].num;
if(c[x][]!=)
tr[x].min=min(tr[x].min,tr[c[x][]].min);
if(c[x][]!=)
tr[x].min=min(tr[x].min,tr[c[x][]].min);
tr[x].min+=tr[x].plus;
}
void down(int x)
{
if(tr[x].rev)
swap(c[x][],c[x][]),tr[c[x][]].rev^=,tr[c[x][]].rev^=,tr[x].rev=;
if(tr[x].plus)
tr[c[x][]].plus+=tr[x].plus,tr[c[x][]].plus+=tr[x].plus,
tr[x].num+=tr[x].plus,tr[x].plus=,up(c[x][]),up(c[x][]);
}
void rot(int x)
{
down(fa[x]);down(x);
int y=fa[x],k=c[y][]==x;
if(fa[y]) c[fa[y]][c[fa[y]][]==y]=x;
else rt=x;
fa[x]=fa[y];fa[y]=x;
c[y][k]=c[x][!k];
if(c[x][!k])
fa[c[x][!k]]=y;
c[x][!k]=y;
up(y);up(x);
}
void splay(int x,int z)
{
for(int y;(y=fa[x])!=z;rot(x))
if(fa[y]!=z)
rot(c[fa[y]][]==y^c[y][]==x?x:y);
}
int Find(int x)
{
if(x==) return -;
if(x>tr[rt].size) return -;
int now=rt;
while(down(now),tr[c[now][]].size+!=x)
if(x<=tr[c[now][]].size)
now=c[now][];
else
x-=tr[c[now][]].size+,now=c[now][];
return now;
}
int split(int x,int y)
{
if(x== && y==tr[rt].size)
return rt;
if(x==)
{ splay(Find(y+),);return c[rt][];}
if(y==tr[rt].size)
{ splay(Find(x-),);return c[rt][];}
splay(Find(x-),);
splay(Find(y+),rt);
return c[c[rt][]][];
}
void upd(int x)
{
int len=;
while(x)
lin[++len]=x,x=fa[x];
for(int i=len;i;i--)
down(lin[i]);
for(int i=;i<=len;i++)
up(lin[i]);
}
int Split(int x,int y)
{
int p=split(x,y),q=fa[p];
upd(p);
fa[p]=;c[q][c[q][]==p]=;
upd(q);
splay(q,);
return p;
}
void work(int x,int y)
{
RT=top[x];int tem;
if(cmd[]=='c')
tr[tem=split(num(x),num(y))].plus+=z,upd(tem);//?
if(cmd[]=='S')
ret+=ans.sum;
if(cmd[]=='a') ret=max(ret,(ll)ans.max);
if(cmd[]=='i') RET=min(RET,ans.min);
if(cmd[]=='v')
{
int tem=Split(num(x),num(y));
if(tem==rt) die[RT]=;
RT=n+;
if(!rt) rt=tem;
else
{
splay(Find(),);
c[rt][]=tem;fa[tem]=rt;
splay(tem,);
}
}
}
void add(int p,int q)
{
to[++E]=q;nex[E]=fir[p];fir[p]=E;
}
int build(int now,int fat)
{
size[now]=;Fa[now]=fat;dep[now]=dep[fat]+;
for(int i=fir[now];i;i=nex[i])
if(to[i]!=fat)
size[now]+=build(to[i],now);
return size[now];
}
void ins()
{
int now=rt;
while(c[now][]) now=c[now][];
c[now][]=++NODE;fa[NODE]=now;
tr[NODE]=trnode();
splay(NODE,);
}
void pou(int now,int Top)
{
top[now]=Top;
if(Top==now)
tr[++NODE]=trnode(),root[now]=NODE;
else
RT=Top,ins();
int id=;
for(int i=fir[now];i;i=nex[i])
if(to[i]!=Fa[now])
if(size[to[i]]>size[id])
id=to[i];
if(id) pou(id,Top);
for(int i=fir[now];i;i=nex[i])
if(to[i]!=Fa[now] && to[i]!=id)
pou(to[i],to[i]);
}
int main()
{
scanf("%d%d%d",&n,&m,&R);
for(int i=;i<n;i++)
scanf("%d%d",&p,&q),
add(p,q),add(q,p);
tr[].size=;
build(R,);
pou(R,R);
for(int i=;i<=m;i++)
{
if(i==)
int e=;
scanf("%s%d%d",cmd,&x,&y);
if(cmd[]=='c') scanf("%d",&z);
ret=;RET=INF;sttop=;
while(top[x]!=top[y])
{
if(dep[top[x]]<dep[top[y]]) swap(x,y);
work(top[x],x);
st[++sttop]=top[x];sz[sttop]=num(x);
x=Fa[top[x]];
}
if(dep[x]>dep[y])
swap(x,y);
if(cmd[]=='v')
{
RT=top[x];
inv_x=Find(num(x)-);inv_y=Find(num(y)+);
}
work(x,y);
if(cmd[]=='S' || cmd[]=='a') printf("%lld\n",ret);
if(cmd[]=='i') printf("%d\n",RET);
if(cmd[]=='v')
{
RT=n+;
tr[rt].rev^=;
int tem=Split(,num(y)-num(x)+);
RT=top[x];
if(inv_x==- && inv_y==-)
rt=tem,die[RT]=;
else
if(inv_x==-)
{
splay(inv_y,);
c[rt][]=tem;fa[tem]=rt;
splay(tem,);
}
else
if(inv_y==-)
splay(inv_x,),c[rt][]=tem,fa[tem]=rt,splay(tem,);
else
splay(inv_x,),splay(inv_y,rt),c[c[rt][]][]=tem,fa[tem]=c[rt][],splay(tem,);
for(int i=sttop;i;i--)
{
RT=n+;
int tem=Split(,sz[i]);
RT=st[i];
if(die[RT]) die[RT]=,rt=tem;
else
{
splay(Find(),);
c[rt][]=tem;fa[tem]=rt;splay(tem,);
}
}
}
root[n+]=;die[n+]=;
}
return ;
}

bzoj3159决战 码农题 树剖套splay的更多相关文章

  1. 【小技巧】树剖套线段树优化建图如何做到 O(nlogn)

    前提:用树剖套线段树优化树链连边.例题:bzoj4699 我们说树剖的时间复杂度是 $O(n\times log(n))$,是因为访问一条链时需要经过 $log(n)$ 级别条重链,对于每条重链还需要 ...

  2. codechef FIBTREE 码农题 线段树 树剖 标记永久化

    好烦啊,调了半天 线段树部分标记比较多,手抖打错了一个 剩下的都是取模的问题 我自己瞎jb推的公式里保留了abs,但是在模意义下是gg的,所以必须把正负区分开 调试的时候一定要注意构造各种形状的树,不 ...

  3. BZOJ 2157 旅行(树链剖分码农题)

    写了5KB,1发AC... 题意:给出一颗树,支持5种操作. 1.修改某条边的权值.2.将u到v的经过的边的权值取负.3.求u到v的经过的边的权值总和.4.求u到v的经过的边的权值最大值.5.求u到v ...

  4. 洛谷P4315 月下“毛景树”(树剖+线段树)

    传送门 woc这该死的码农题…… 把每一条边转化为它连接的两点中深度较深的那一个,然后就可以用树剖+线段树对路径进行修改了 然后顺便注意在上面这种转化之后,树剖的时候不能搞$LCA$ 然后是几个注意点 ...

  5. 洛谷P1505 [国家集训队]旅游(树剖+线段树)

    传送门 这该死的码农题…… 把每一条边变为它连接的两个点中深度较浅的那一个,然后就是一堆单点修改/路径查询,不讲了 这里就讲一下怎么搞路径取反,只要打一个标记就好了,然后把区间和取反,最大最小值交换然 ...

  6. 洛谷P3250 [HNOI2016]网络(整体二分+树状数组+树剖)

    传送门 据说正解是树剖套堆???然而代码看着稍微有那么一点点长…… 考虑一下整体二分,设当前二分到的答案为$mid$,如果所有大于$mid$的边都经过当前点$x$,那么此时$x$的答案必定小于等于$m ...

  7. 【BZOJ 3196】二逼平衡树 线段树套splay 模板题

    我写的是线段树套splay,网上很多人写的都是套treap,然而本蒟蒻并不会treap 奉上sth神犇的模板: //bzoj3196 二逼平衡树,支持修改某个点的值,查询区间第k小值,查询区间某个值排 ...

  8. P4175 [CTSC2008]网络管理 树剖+树套树

    $ \color{#0066ff}{ 题目描述 }$ M公司是一个非常庞大的跨国公司,在许多国家都设有它的下属分支机构或部门.为了让分布在世界各地的N个部门之间协同工作,公司搭建了一个连接整个公司的通 ...

  9. 洛谷树剖模板题 P3384 | 树链剖分

    原题链接 对于以u为根的子树,后代节点的dfn显然比他的dfn大,我们可以记录一下回溯到u的dfn,显然这两个dfn构成了一个连续区间,代表u及u的子树 剩下的就和树剖一样了 #include< ...

随机推荐

  1. html5--2.3新的布局元素(2)-article

    html5--2.3新的布局元素(2)-article 学习要点 了解article元素的语义和用法 完成一个简单的实例 article元素(标签) 用于定义一个独立的内容区块,比如一篇文章,一篇博客 ...

  2. codeforces 660C C. Hard Process(二分)

    题目链接: C. Hard Process time limit per test 1 second memory limit per test 256 megabytes input standar ...

  3. HDU5875Function(单调队列)

    The shorter, the simpler. With this problem, you should be convinced of this truth.      You are giv ...

  4. ACM学习历程—Hihocoder编程之美测试赛B题 大神与三位小伙伴(组合数学 )

    时间限制:2000ms 单点时限:1000ms 内存限制:256MB 描述 给你一个m x n (1 <= m, n <= 100)的矩阵A (0<=aij<=10000),要 ...

  5. bzoj 4671 异或图 —— 容斥+斯特林反演+线性基

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4671 首先,考虑容斥,就是设 \( t[i] \) 表示至少有 \( i \) 个连通块的方 ...

  6. 《TCP/IP详解卷一:协议》 概述

    分层           TCP/IP协议族是一组不同层次上的多个协议的组合.TCP/IP通常被认为是一个四层次协议系统.   链路层(数据链路层或网络接口层):通常包括操作系统中的设备驱动程序和计算 ...

  7. SimpliciTI APP

    SimpliciTI Sample Applications   Sample Applications 介绍了4个简单的示例应用程序来演示SimpliciTI的各种特性和功能. Simple Pee ...

  8. 常见的post提交数据类型

    原文地址:https://www.cnblogs.com/yoyoketang/p/6771696.html 常见的post提交数据类型有四种: 1.第一种:application/json:这是最常 ...

  9. Jenkins Email Extension Plugin 邮件插件

    1:系统管理-管理插件-可选插件  搜索Email 可列出Email Extension Plugin插件 2:选择相应的插件点  下载并安装之后重启,等待 3:安装完后,自己去重启tomcat,先s ...

  10. 【244】◀▶IEW-Unit09

    Unit 9 Food 1)Model1题目及范文讲解 In the world today, there is a problem with food production. As a result ...