【BZOJ1036】【LCT版】树的统计Count
Description
一 棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w。我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值 III. QSUM u v: 询问从点u到点v的路径上的节点的权值和 注意:从点u到点v的路径上的节点包括u和v本身
Input
输 入的第一行为一个整数n,表示节点的个数。接下来n – 1行,每行2个整数a和b,表示节点a和节点b之间有一条边相连。接下来n行,每行一个整数,第i行的整数wi表示节点i的权值。接下来1行,为一个整数 q,表示操作的总数。接下来q行,每行一个操作,以“CHANGE u t”或者“QMAX u v”或者“QSUM u v”的形式给出。 对于100%的数据,保证1<=n<=30000,0<=q<=200000;中途操作中保证每个节点的权值w在-30000到 30000之间。
Output
对于每个“QMAX”或者“QSUM”的操作,每行输出一个整数表示要求输出的结果。
Sample Input
4
1 2
2 3
4 1
4 2 1 3
12
QMAX 3 4
QMAX 3 3
QMAX 3 2
QMAX 2 3
QSUM 3 4
QSUM 2 1
CHANGE 1 5
QMAX 3 4
CHANGE 3 6
QMAX 3 4
QMAX 2 4
QSUM 3 4
Sample Output
4
1
2
2
10
6
5
6
5
16
Hint
【分析】
随便写了一个LCT的版本,比树链剖分慢...
现在发现LCT真是个好东西,好写又有用。
/*
唐代白居易
《白云泉》
天平山上白云泉,云自无心水自闲。
何必奔冲山下去,更添波浪向人间。
*/
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <vector>
#include <utility>
#include <iomanip>
#include <string>
#include <cmath>
#include <queue>
#include <assert.h>
#include <map>
#include <ctime>
#include <cstdlib>
#include <stack>
#define LOCAL
const int INF = 0x7fffffff;
const int MAXN = + ;
const int maxnode = ;
const int maxm= * + ;
using namespace std; struct Link_Cut_Tree{
struct Node{
int val, sum, Max;//用来debug
int delta;
Node *parent;
Node *ch[];
}node[MAXN], *cur, _null, *null;
Node *tmp[MAXN]; bool is_root(Node* t){//判断是否是splay的根
if (t == null || (t->parent->ch[] != t && t->parent->ch[] != t)) return ;
return ;
}
//本来以为不要pushdown了,结果还是要
void pushdown(Node *t){
if (t == null) return;
if (t->delta){
t->delta = ;
if (t->ch[] != null) t->ch[]->delta ^= ;
if (t->ch[] != null) t->ch[]->delta ^= ;
swap(t->ch[], t->ch[]);
}
}
//更新
void update(Node *t){
if (t == null) return;
t->sum = t->val;
if (t->ch[] != null) t->sum += t->ch[]->sum;
if (t->ch[] != null) t->sum += t->ch[]->sum;
t->Max = max(t->val, max(t->ch[]->Max, t->ch[]->Max));
return;
}
void init(){
null = &_null;
_null.val = _null.sum = _null.Max = -INF;
_null.delta = ;
_null.parent = _null.ch[] = _null.ch[] = null; cur = node + ;
}
Node* NEW(int val){
cur->parent = cur->ch[] = cur->ch[] = null;
cur->val = cur->Max = cur->sum = val;
cur->delta = ;
return cur++;
}
void rotate(Node *t, int d){
if (is_root(t)) return;
Node *p = t->parent;
p->ch[d ^ ] = t->ch[d];
if (t->ch[d] != null) t->ch[d]->parent = p;
t->parent = p->parent;
if (p != null){
if (p->parent->ch[] == p) p->parent->ch[] = t;
else if (p->parent->ch[] == p) p->parent->ch[] = t;
}
t->ch[d] = p;
p->parent = t;
update(t);
update(p);//真逗,什么都不要
}
//将t旋转到根
void splay(Node *t){
//标记下传
int cnt = ;
tmp[] = t;
for (Node *y = t; !is_root(y); y = y->parent) tmp[cnt++] = y->parent;
while (cnt) pushdown(tmp[--cnt]); while (!is_root(t)){
Node *y = t->parent;
if (is_root(y)) rotate(t, (y->ch[] == t));
else {
int d = (y->parent->ch[] == y);
if (y->ch[d] == t) rotate(t, d ^ );
else rotate(y, d);
rotate(t, d);
}
update(t);
}
update(t);
}
Node* access(Node *t){
Node *p = null;
while (t != null){
splay(t);
if (p != null) p->parent = t;
t->ch[] = p;
update(t);
p = t;
t = t->parent;
}
return p;
}
//合并u,v所在的树
void merge(Node *u, Node *v){
access(u);
splay(u);
u->delta = ;
u->parent = v;
return;
}
void cut(Node *u, Node *v){
access(u)->delta ^= ;
//splay(u);//转到顶上就切断v就可以了
access(v);
splay(v); v->ch[]->parent = null;
v->ch[] = null;
return;
}
//找根
Node *find(Node *t){
access(t);
splay(t);
while (t->parent != null) t = t->parent;
return t;
}
bool check(Node *u, Node *v){
while (u->parent != null) u = u->parent;
while (v->parent != null) v = v->parent;
return (u == v);
}
void change(Node *l, int x){
access(l);
splay(l);
l->val = x;
update(l);
}
}splay;
int n, m;
int u[MAXN] , v[MAXN]; void init(){
splay.init();
scanf("%d", &n);
for (int i = ; i < n; i++) scanf("%d%d", &u[i], &v[i]);
for (int i = ; i <= n; i++){
int a;
scanf("%d", &a);
splay.NEW(a);
}
for (int i = ; i < n; i++)
splay.merge(splay.node + u[i], splay.node + v[i]);
}
void work(){
int m ;
scanf("%d", &m);
for (int i = ; i <= m; i++){
char str[];
scanf("%s", str);
if (str[] == 'C'){
int l, x;
scanf("%d%d", &l, &x);//将l的值改为x
splay.change(splay.node + l, x);
}else if (str[] == 'Q'){
int l, r;
scanf("%d%d", &l, &r);
if (str[] == 'S'){
splay.access(splay.node + l)->delta ^= ;//换根
splay.access(splay.node + r);
Link_Cut_Tree::Node *p = splay.find(splay.node + r);
printf("%d\n", p->sum);
}else{//求最大值
splay.access(splay.node + l)->delta ^= ;//换根
splay.access(splay.node + r);
Link_Cut_Tree::Node *p = splay.find(splay.node + r);
printf("%d\n", p->Max);
}
}
}
} int main (){ init();
work();
return ;
}
【BZOJ1036】【LCT版】树的统计Count的更多相关文章
- 【BZOJ1036】[ZJOI2008]树的统计Count 树链剖分
[BZOJ1036][ZJOI2008]树的统计Count Description 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w.我们将以下面的形式来要求你对这棵树完成一些操作: I. ...
- 【bzoj1036】 ZJOI2008—树的统计Count
http://www.lydsy.com/JudgeOnline/problem.php?id=1036 (题目链接) 题意 动态维护树上两点间最大权值和权值和. Solution 裸树链剖分. 这一 ...
- 【bzoj1036】[ZJOI2008]树的统计Count
题目描述 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w.我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u v ...
- 【bzoj1036】[ZJOI2008]树的统计Count 树链剖分+线段树
题目描述 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w.我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u v ...
- 【BZOJ1036】[ZJOI2008] 树的统计Count(一道可怕的模板题:树剖+线段树)
点此看题面 题解 这真的只是一道模板题:一个树链剖分套上一个线段树(令我窒息的组合). 既然是模板题,那就直接上代码吧. 代码 #include<bits/stdc++.h> #defin ...
- Bzoj 1036: [ZJOI2008]树的统计Count 树链剖分,LCT
1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 11102 Solved: 4490[Submit ...
- [BZOJ1036][ZJOI2008]树的统计Count 解题报告|树链剖分
树链剖分 简单来说就是数据结构在树上的应用.常用的为线段树splay等.(可现在splay还不会敲囧) 重链剖分: 将树上的边分成轻链和重链. 重边为每个节点到它子树最大的儿子的边,其余为轻边. 设( ...
- Cogs 1688. [ZJOI2008]树的统计Count(树链剖分+线段树||LCT)
[ZJOI2008]树的统计Count ★★★ 输入文件:bzoj_1036.in 输出文件:bzoj_1036.out 简单对比 时间限制:5 s 内存限制:162 MB [题目描述] 一棵树上有n ...
- bzoj1036 [ZJOI2008]树的统计Count
1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec Memory Limit: 162 MB Submit: 12646 Solved: 5085 [Subm ...
- BZOJ-1036 树的统计Count 链剖线段树(模板)=(树链剖分+线段树)
潇爷昨天刚刚讲完...感觉得还可以...对着模板打了个模板...还是不喜欢用指针.... 1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec Memory Lim ...
随机推荐
- 【转】在Ubuntu下编译Android源码并运行Emulator
原文网址:http://www.mcuos.com/thread-4553-1-1.html 建立编译环境 1.在VirtualBox上安装Ubuntu 2.安装JDK $ sudo apt-ge ...
- 关于android屏幕适配
好吧 我承认被美工虐的够呛,而且美工他么是个男的!一点也不美, 废话不多说 急着赶路, 之前不怎么重视 直到遇见这个美工给我一套1080x1920的 图,没错 就一套 1dp=3px没错的啊 问题是就 ...
- oracle自动编号
oracle自动编号 在access中有自动编号的数据类型,MSSQL和MYSQL也都有自动增长的数据类型,插入记录时不用操作此字段,会自动获得数据值,而oracle没有自动增长的数据类型,我们需要建 ...
- mac下的改装人生——关于ssd
这两天研究了很多关于ssd的东西,想想还是写下来把,毕竟花了这么多时间进去. 先说一下我自己的电脑把.前几天,因为嫌我的电脑是在是太卡了,准备来次升级,然后先买了个8g的内存装上,发现的确是没有死机的 ...
- A*寻路算法的探寻与改良(一)
A*寻路算法的探寻与改良(一) by:田宇轩 第一部分:这里我们主 ...
- 简单的LR核心项集和Goto表填充演示程序
/* * 该程序用于计算语言的核心项集 * RexfieldVon * 2013年8月24日21:19:25 */ #include <stdio.h> #include <stdl ...
- POI HSSFColor 颜色索引对照表
POI HSSFColor 颜色索引对照表 . HSSFColor.GREY_80_PERCENT . HSSFColor.INDIGO . HSSFColor.PLUM HSSFColor.BROW ...
- java poi操作excel 添加 锁定单元格保护
Excel的book保护是很常用的,主要是不想让别人修改Excel的时候用.这样能够避免恶意随便修改数据,提高数据的可信度. 下面介绍JAVA POI来实现设置book保护: 使用HSSFSheet类 ...
- RGB的三维模型与渐变色-颜色系列之一
一.前言 以下与颜色相关的日志记录了俺学习颜色的有关容,限于编写时的水平,难免存在缺点与错误,希望得到朋友.同行和前辈的指教,非常感谢.1. RGB的三维模型与渐变色-颜色系列之一2. <颜 ...
- PHP面向对象之旅:抽象类继承抽象类(转)
可以理解为对抽象类的扩展 抽象类继承另外一个抽象类时,不用重写其中的抽象方法.抽象类中,不能重写抽象父类的抽象方法.这样的用法,可以理解为对抽象类的扩展. 下面的例子,演示了一个抽象类继承自另外一个抽 ...