【xsy1019】小A的树论
题意
三种操作:
①区间增值
②某一个点换父亲
③求子树和
\(1\leq n\leq 100000\)
分析
Splay维护dfn序。
小结
(1)使用Splay,通常要在Splay的两端各添加一个虚拟节点,防止没有前驱和后继的情况。
(2)使用Splay的时候,要注意我们的key值是什么,与附加值进行区分。
(3)在父亲连接儿子的时候,如果我们也存父亲的情况,那么要记得儿子连向父亲。
(4)Splay是一种很难调试的数据结构,所以要掌握一种技巧:静态调试。
void Traver(int x) {
if (!x) return;
Traver(tr[x].c[0]);
printf("%d ",x);
Traver(tr[x].c[1]);
}
(5)这类知道对应点位置,不知道其在树上位置的题,通常用Splay来解决。因为Treap要进行合并和分裂,需要知道在树上的位置。当然有一些处理方法:①记录父亲 ②相同权值不同化,记一个pair
(6)只有换根:分类讨论
定向link-cut:Splay维护dfn序
(7)把树变成链的三种序列:①每个出现一次 ②每个出现两次 ③每个出现度数次
代码
#pragma comment(linker, "/STACK:102400000,102400000")
#include <cstdio>
#include <cctype>
#include <algorithm>
#include <vector>
using namespace std;
#define rep(i,a,b) for (int i=(a);i<=(b);i++)
#define per(i,a,b) for (int i=(a);i>=(b);i--)
#define lc tr[x].c[0]
#define rc tr[x].c[1]
#define pb push_back
typedef long long LL;
const int N=131072;
const int S=262144;
int n,m;
int w[N];
vector<int> g[N];
int tot;
int s[N],e[N];
struct Tree {
int c[2]; int fa;
int sz;
LL val,sum,tag;
Tree(int _lc=0,int _rc=0,int _fa=0,LL _val=0) {
c[0]=_lc,c[1]=_rc,fa=_fa;
sz=1;
val=_val; sum=_val; tag=0;
}
}tr[S];
int st[S],len;
LL rd(void) {
LL x=0,f=1; char c=getchar();
while (!isdigit(c)) {
if (c=='-') f=-1;
c=getchar();
}
while (isdigit(c)) {
x=x*10+c-'0';
c=getchar();
}
return x*f;
}
void DFS(int x,int fa) {
tot++; st[tot]=x; s[x]=tot;
rep(i,1,g[x].size()) {
int nx=g[x][i-1];
if (nx!=fa)
DFS(nx,x);
}
tot++; st[tot]=x; e[x]=tot;
}
void Pushup(int x) {
tr[x].sz=tr[lc].sz+tr[rc].sz+1;
tr[x].sum=tr[lc].sum+tr[rc].sum+tr[x].val;
}
void Clear(int x) {
if (tr[x].tag!=0) {
if (lc>0) {
tr[lc].val+=tr[x].tag;
tr[lc].tag+=tr[x].tag;
tr[lc].sum+=tr[x].tag*tr[lc].sz;
}
if (rc>0) {
tr[rc].val+=tr[x].tag;
tr[rc].tag+=tr[x].tag;
tr[rc].sum+=tr[x].tag*tr[rc].sz;
}
tr[x].tag=0;
}
}
void Rotate(int x) {
int y=tr[x].fa,z=tr[y].fa;
int l=!(tr[y].c[0]==x),r=l^1;
if (z>0) {
if (tr[z].c[0]==y)
tr[z].c[0]=x;
else tr[z].c[1]=x;
}
tr[x].fa=z; tr[y].fa=x;
if (tr[x].c[r]>0) tr[tr[x].c[r]].fa=y;
tr[y].c[l]=tr[x].c[r]; Pushup(y);
tr[x].c[r]=y; Pushup(x);
}
void Tsunami(int x) {
len=0; st[++len]=x;
for (int i=x;tr[i].fa>0;i=tr[i].fa)
st[++len]=tr[i].fa;
per(i,len,1) Clear(st[i]);
}
void Splay(int x,int rt=0) {
Tsunami(x);
while (tr[x].fa!=rt) {
int y=tr[x].fa,z=tr[y].fa;
if (z!=rt) {
if ((tr[y].c[0]==x)^(tr[z].c[0]==y))
Rotate(x);
else Rotate(y);
}
Rotate(x);
}
}
int Pre(int x) {
Splay(x);
x=lc; while (rc>0) x=rc;
return x;
}
int Nxt(int x) {
Splay(x);
x=rc; while (lc>0) x=lc;
return x;
}
LL Sum_Sub(int x) {
int l=s[x],r=e[x];
l=Pre(l),r=Nxt(r);
Splay(l); Splay(r,l);
return tr[tr[r].c[0]].sum;
}
void Add_Sub(int x,int y) {
int l=s[x],r=e[x];
l=Pre(l),r=Nxt(r);
Splay(l); Splay(r,l);
tr[tr[r].c[0]].val+=y;
tr[tr[r].c[0]].tag+=y;
tr[tr[r].c[0]].sum+=(LL)tr[tr[r].c[0]].sz*y;
Pushup(r); Pushup(l);
}
void Link_Cut(int x,int y) {
int l=s[x],r=e[x];
l=Pre(l),r=Nxt(r);
Splay(l); Splay(r,l);
int t=tr[r].c[0]; tr[r].c[0]=0; Pushup(r); Pushup(l);
int sy=s[y],ny=Nxt(sy);
Splay(sy); Splay(ny,sy);
tr[ny].c[0]=t; tr[t].fa=ny; Pushup(ny); Pushup(sy);
}
void Traver(int x) {
if (!x) return;
Traver(tr[x].c[0]);
printf("%d ",x);
Traver(tr[x].c[1]);
}
int main(void) {
#ifndef ONLINE_JUDGE
freopen("sd.in","r",stdin);
freopen("sd.out","w",stdout);
#endif
n=rd(),m=rd();
rep(i,1,n) w[i]=rd();
rep(i,1,n-1) {
int x=rd(),y=rd();
g[x].pb(y),g[y].pb(x);
}
DFS(1,-1);
rep(i,1,n) {
tr[s[i]]=Tree(0,s[i]+1,s[i]-1,w[i]);
tr[e[i]]=Tree(0,e[i]+1,e[i]-1,w[i]);
}
tr[0].sz=0;
tr[tot].c[1]=tot+1; tr[tot+1]=Tree(0,0,tot,0);
tr[tot+2]=Tree(0,1,0,0); tr[1].fa=tot+2;
per(i,tot,1) Pushup(i); Pushup(tot+2);
rep(i,1,m) {
int kd=rd(); int x,y; LL res;
switch (kd) {
case 1:
x=rd();
res=Sum_Sub(x)>>1;
printf("%lld\n",res);
break;
case 2:
x=rd(),y=rd();
Add_Sub(x,y);
break;
case 3:
x=rd(),y=rd();
Link_Cut(x,y);
break;
}
// Splay(1); Traver(1); printf("\n");
}
return 0;
}
【xsy1019】小A的树论的更多相关文章
- 小机房的树 codevs 2370
2370 小机房的树 时间限制: 1 s 空间限制: 256000 KB 题目等级 : 钻石 Diamond 题解 查看运行结果 题目描述 Description 小机房有棵焕狗种的树 ...
- 【codevs2370】小机房的树 LCA 倍增
2370 小机房的树 时间限制: 1 s 空间限制: 256000 KB 题目等级 : 钻石 Diamond 题目描述 Description 小机房有棵焕狗种的树,树上有N个节点,节点标号为0 ...
- Codevs 2370 小机房的树
2370 小机房的树 时间限制: 1 s 空间限制: 256000 KB 题目等级 : 钻石 Diamond 传送门 题目描述 Description 小机房有棵焕狗种的树,树上有N个节点,节点标号为 ...
- 牛客挑战赛30 小G砍树 树形dp
小G砍树 dfs两次, dp出每个点作为最后一个点的方案数. #include<bits/stdc++.h> #define LL long long #define fi first # ...
- CodeVs.2370 小机房的树 ( LCA 倍增 最近公共祖先)
CodeVs.2370 小机房的树 ( LCA 倍增 最近公共祖先) 题意分析 小机房有棵焕狗种的树,树上有N个节点,节点标号为0到N-1,有两只虫子名叫飘狗和大吉狗,分居在两个不同的节点上.有一天, ...
- LCA(倍增在线算法) codevs 2370 小机房的树
codevs 2370 小机房的树 时间限制: 1 s 空间限制: 256000 KB 题目等级 : 钻石 Diamond 题目描述 Description 小机房有棵焕狗种的树,树上有N个节点, ...
- 【BZOJ5072】[Lydsy十月月赛]小A的树 树形DP
[BZOJ5072][Lydsy十月月赛]小A的树 题解:考虑我们从一个联通块中替换掉一个点,导致黑点数量的变化最多为1.所以我们考虑维护对于所有的x,y的最大值和最小值是多少.如果询问的y在最大值和 ...
- codevs——2370 小机房的树
2370 小机房的树 时间限制: 1 s 空间限制: 256000 KB 题目等级 : 钻石 Diamond 题解 题目描述 Description 小机房有棵焕狗种的树,树上有N个 ...
- codevs2370 小机房的树 x
2370 小机房的树 时间限制: 1 s 空间限制: 256000 KB 题目等级 : 钻石 Diamond 题目描述 Description 小机房有棵焕狗种的树,树上有N个节点,节点标号 ...
随机推荐
- mongodb的使用
1.启动mongodb 启动mongodb在Linux中可以进入mongodb的bin目录下执行 ./mongod -dbpath=所建立的数据文件夹 -logpath=所建立的日志文件 ...
- 使用Java字节流拷贝文件
本文给出使用Java字节流实现文件拷贝的例子 package LearnJava; import java.io.*; public class FileTest { public static vo ...
- copy file to docker from realhost
http://blog.e3rp4y.me/blog/2014/05/23/copy-file-from-host-to-docker.html --------------------------- ...
- 《30天自制操作系统》13_day_学习笔记
harib10a: 简化字符串的显示:我们发现字符串显示三条语句总是重复出现,并且总是一起出现的.接下来我们把它归纳到一个函数中,这样便于使用. x,y--位置的坐标 c--字符颜色 (col ...
- Windows消息传递机制详解
Windows是一个消息(Message)驱动系统.Windows的消息提供了应用程序之间.应用程序与Windows系统之间进行通信的手段.应用程序想要实现的功能由消息来触发,并且靠对消息的响应和处理 ...
- 复制 replication 新增表 add new article
immediate_sync false Synchronization files are created only if there are new subscriptions. Subs ...
- [CrunchBang]tint2默认设置
#--------------------------------------------- # TINT2 CONFIG FILE #-------------------------------- ...
- TCMalloc的使用
Windows下: 1. 编译libtcmalloc_minimal,编成静态的动态的都可以. 2. 在链接中设置附加依赖库libtcmalloc_minimal.lib,并且强制符号引用要加上__t ...
- UICollectionViewDelegateFlowLayout 使用
import UIKit //UICollectionViewLayout //itemSize属性 //设定全局的Cell尺寸,如果想要单独定义某个Cell的尺寸,可以使用下面方法: // - (C ...
- win7下JDK环境变量设置方法
来源于:http://jingyan.baidu.com/article/e9fb46e1b2b3347521f766c1.html