HDU 5002 Tree(动态树LCT)(2014 ACM/ICPC Asia Regional Anshan Online)
Your task is to deal with M operations of 4 types:
1.Delete an edge (x, y) from the tree, and then add a new edge (a, b). We ensure that it still constitutes a tree after adding the new edge.
2.Given two nodes a and b in the tree, change the weights of all the nodes on the path connecting node a and b (including node a and b) to a particular value x.
3.Given two nodes a and b in the tree, increase the weights of all the nodes on the path connecting node a and b (including node a and b) by a particular value d.
4.Given two nodes a and b in the tree, compute the second largest weight on the path connecting node a and b (including node a and b), and the number of times this weight occurs on the path. Note that here we need the strict second largest weight. For instance, the strict second largest weight of {3, 5, 2, 5, 3} is 3.
For each test case, the first line contains two integers N and M (N, M<=10^5). The second line contains N integers, and the i-th integer is the weight of the i-th node in the tree (their absolute values are not larger than 10^4).
In next N-1 lines, there are two integers a and b (1<=a, b<=N), which means there exists an edge connecting node a and b.
The next M lines describe the operations you have to deal with. In each line the first integer is c (1<=c<=4), which indicates the type of operation.
If c = 1, there are four integers x, y, a, b (1<= x, y, a, b <=N) after c.
If c = 2, there are three integers a, b, x (1<= a, b<=N, |x|<=10^4) after c.
If c = 3, there are three integers a, b, d (1<= a, b<=N, |d|<=10^4) after c.
If c = 4 (it is a query operation), there are two integers a, b (1<= a, b<=N) after c.
All these parameters have the same meaning as described in problem description.
For each query operation, output two values: the second largest weight and the number of times it occurs. If the weights of nodes on that path are all the same, just output "ALL SAME" (without quotes).
题目大意:维护一棵树,每次删边加边、给一条路径的所有点赋一个值、给一条路径的所有点加上一个值,或询问一条路径上的第二大值及其在这条路径上的出现次数。
思路:算是LCT的模板题吧,维护每个区间的第一大值和第一大值的出现次数,第二大值和第二大值的出现次数。
PS:终于搞出了一个指针版,新模板出来啦~~~
犯过的错误:
1、LCT里splay的旋转和普通splay的旋转有所不同。
2、不能更新超级儿子 nil 的最值。
代码(2859MS):
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std;
typedef long long LL;
#define FOR(i, n) for(int i = 0; i < n; ++i) const int MAXV = ;
const int MAXE = MAXV << ;
const int INF = 0x3f3f3f3f;
const int NINF = -INF; struct LCT {
struct Node {
Node *ch[], *fa;
int val, set, add;
int max[], cnt[], size;
bool rt, rev;
} statePool[MAXV], *nil;
int ncnt; int head[MAXV], val[MAXV], ecnt;
int to[MAXE], next[MAXE];
int n, m, T;
Node *ptr[MAXV]; LCT() {
ptr[] = nil = statePool;
nil->size = ;
FOR(k, ) nil->max[k] = NINF;
} void init() {
memset(head + , -, n * sizeof(int));
ncnt = ;
ecnt = ;
} void add_edge(int u, int v) {
to[ecnt] = v; next[ecnt] = head[u]; head[u] = ecnt++;
to[ecnt] = u; next[ecnt] = head[v]; head[v] = ecnt++;
} Node* new_node(int val, Node *f) {
Node* x = &statePool[ncnt++];
x->ch[] = x->ch[] = nil; x->fa = f;
x->val = val; x->set = NINF; x->add = ;
x->max[] = val; x->cnt[] = ;
x->max[] = NINF;
x->size = ;
x->rt = true; x->rev = false;
return x;
} void dfs(int u, int f) {
ptr[u] = new_node(val[u], ptr[f]);
for(int p = head[u]; ~p; p = next[p]) {
int v = to[p];
if(v == f) continue;
dfs(v, u);
}
} void get_max(int &a, int &b, int c) {
if(a != c) {
if(b < c) swap(b, c);
if(a < b) swap(a, b);
}
} void cnt_max(int a, int &cnt, int b, int bcnt) {
if(a != NINF && a == b) cnt += bcnt;
} void update(Node *x) {
x->size = x->ch[]->size + x->ch[]->size + ; x->max[] = x->val; x->max[] = NINF;
FOR(i, ) FOR(j, )
get_max(x->max[], x->max[], x->ch[i]->max[j]); FOR(k, ) x->cnt[k] = ;
FOR(k, ) cnt_max(x->max[k], x->cnt[k], x->val, );
FOR(k, ) FOR(i, ) FOR(j, )
cnt_max(x->max[k], x->cnt[k], x->ch[i]->max[j], x->ch[i]->cnt[j]);
} void rotate(Node *x) {
Node *y = x->fa;
int t = (y->ch[] == x); if(y->rt) y->rt = false, x->rt = true;
else y->fa->ch[y->fa->ch[] == y] = x;
x->fa = y->fa; (y->ch[t] = x->ch[t ^ ])->fa = y;
(x->ch[t ^ ] = y)->fa = x;
update(y);
} void update_set(Node *x, int val) {
if(x == nil) return ;
x->add = ;
x->val = x->set = val;
x->max[] = val; x->cnt[] = x->size;
x->max[] = NINF;
} void update_add(Node *x, int val) {
if(x == nil) return ;
x->add += val;
x->val += val;
FOR(k, ) if(x->max[k] != NINF)
x->max[k] += val;
} void update_rev(Node *x) {
if(x == nil) return ;
x->rev = !x->rev;
swap(x->ch[], x->ch[]);
} void pushdown(Node *x) {
if(x->set != NINF) {
FOR(k, ) update_set(x->ch[k], x->set);
x->set = NINF;
}
if(x->add != ) {
FOR(k, ) update_add(x->ch[k], x->add);
x->add = ;
}
if(x->rev) {
FOR(k, ) update_rev(x->ch[k]);
x->rev = false;
}
} void push(Node *x) {
if(!x->rt) push(x->fa);
pushdown(x);
} void splay(Node *x) {
push(x);
while(!x->rt) {
Node *f = x->fa, *ff = f->fa;
if(!f->rt) rotate(((ff->ch[] == f) && (f->ch[] == x)) ? f : x);
rotate(x);
}
update(x);
} Node* access(Node *x) {
Node *y = nil;
while(x != nil) {
splay(x);
x->ch[]->rt = true;
(x->ch[] = y)->rt = false;
update(x);
y = x; x = x->fa;
}
return y;
} void be_root(Node *x) {
access(x);
splay(x);
update_rev(x);
} void link(Node *x, Node *y) {
be_root(x);
x->fa = y;
} void cut(Node *x, Node *y) {
be_root(x);
access(x);
splay(y);
y->fa = nil;
} void modify_add(Node *x, Node *y, int w) {
be_root(x);
update_add(access(y), w);
} void modify_set(Node *x, Node *y, int w) {
be_root(x);
update_set(access(y), w);
} void query(Node *x, Node *y) {
be_root(x);
Node *r = access(y);
if(r->max[] == NINF) puts("ALL SAME");
else printf("%d %d\n", r->max[], r->cnt[]);
} void work() {
scanf("%d", &T);
for(int t = ; t <= T; ++t) {
scanf("%d%d", &n, &m);
init();
for(int i = ; i <= n; ++i) scanf("%d", &val[i]);
for(int i = , u, v; i < n; ++i) {
scanf("%d%d", &u, &v);
add_edge(u, v);
}
dfs(, );
printf("Case #%d:\n", t);
for(int i = , x, y, a, b, op; i < m; ++i) {
scanf("%d", &op);
if(op == ) {
scanf("%d%d%d%d", &x, &y, &a, &b);
cut(ptr[x], ptr[y]);
link(ptr[a], ptr[b]);
} else if(op == ) {
scanf("%d%d%d", &a, &b, &x);
modify_set(ptr[a], ptr[b], x);
} else if(op == ) {
scanf("%d%d%d", &a, &b, &x);
modify_add(ptr[a], ptr[b], x);
} else {
scanf("%d%d", &a, &b);
query(ptr[a], ptr[b]);
}
}
}
}
} S; int main() {
S.work();
}
HDU 5002 Tree(动态树LCT)(2014 ACM/ICPC Asia Regional Anshan Online)的更多相关文章
- HDU 5000 2014 ACM/ICPC Asia Regional Anshan Online DP
Clone Time Limit : 2000/1000ms (Java/Other) Memory Limit : 65536/65536K (Java/Other) Total Submiss ...
- HDU 5000 Clone(离散数学+DP)(2014 ACM/ICPC Asia Regional Anshan Online)
Problem Description After eating food from Chernobyl, DRD got a super power: he could clone himself ...
- 2014 ACM/ICPC Asia Regional Anshan Online
默默的签到 Osu! http://acm.hdu.edu.cn/showproblem.php?pid=5003 #include<cstdio> #include<algorit ...
- hdu 5016 点分治(2014 ACM/ICPC Asia Regional Xi'an Online)
Mart Master II Time Limit: 12000/6000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)T ...
- HDU 5875 Function 【倍增】 (2016 ACM/ICPC Asia Regional Dalian Online)
Function Time Limit: 7000/3500 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)Total ...
- HDU 5029 Relief grain(离线+线段树+启发式合并)(2014 ACM/ICPC Asia Regional Guangzhou Online)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5029 Problem Description The soil is cracking up beca ...
- HDU 5052 Yaoge’s maximum profit 光秃秃的树链拆分 2014 ACM/ICPC Asia Regional Shanghai Online
意甲冠军: 特定n小点的树权. 以下n每一行给出了正确的一点点来表达一个销售点每只鸡价格的格 以下n-1行给出了树的侧 以下Q操作 Q行 u, v, val 从u走v,程中能够买一个鸡腿,然后到后面卖 ...
- hdu 5877 线段树(2016 ACM/ICPC Asia Regional Dalian Online)
Weak Pair Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)Total ...
- HDU 5010 Get the Nut(2014 ACM/ICPC Asia Regional Xi'an Online)
思路:广搜, 因为空格加上动物最多只有32个那么对这32个进行编号,就能可以用一个数字来表示状态了,因为只有 ‘P’ 'S' 'M' '.' 那么就可以用4进制刚好可以用64位表示. 接下去每次就 ...
随机推荐
- day11
JSP入门 1 JSP概述 1.1 什么是JSP JSP(Java Server Pages)是JavaWeb服务器端的动态资源.它与html页面的作用是相同的,显示数据和获取数据. 1.2 ...
- UI---startup--jquery
http://www.w3school.com.cn 传统的基于表单提交, 整页刷新式的并不需要前端MVC. 当 然这种体验会很糟糕.试想一下, 用WebQQ时,每发一次消息页面就要泛白一次, 这是什 ...
- Let's Encrypt这个免费的证书签发服务
使用的是Let's Encrypt这个免费的证书签发服务,按照这里的教程一步步照着来,很快就完成了. 迁移过程总体来说比较顺利,只是遇到了两个不大不小的坑.一个是域名的跳转问题,迁移完成以后对于所有h ...
- angularJS推荐显示注入写法
使用js压缩工具时发现压缩之后的控制器注入参数由原来的$scope变成了a,b...这样的字母而导致js失效,那么我们推荐使用完整的显示注入方式来解决此问题! //隐式注入的写法 angular.mo ...
- Java字符串的那些事儿。。。。
计划围绕以下几个方面 1.内存 2.正则表达式 3.String.format 4.编码 1.内存 先来看个经典的例子 public class Blog { public static void m ...
- 如何迁移测试的MAGENTO到正式运行的MAGENTO
或者这个题目叫做如何改变MAGENTO的运行目录 第一,我们需要在PHPMYADMIN备份整个MAGENTO的数据.备份数据并且存为.SQL. 在这儿假设你的测试网站在http://dev.site. ...
- Selenium2学习-003-WebUI自动化实战实例-001-百度搜索
此文主要通过百度搜索功能,进行 Selenium2 的实战实例讲解,文中所附源代码于 2015-01-16 02:01 亲测通过,敬请亲们阅览.希望能对初学 Selenium2 UI 自动化测试编程的 ...
- action script 3如何检测播放器域
检测播放器域 用户在上面观看媒体内容的网页的 URL 和域并非始终随时可用.如果托管网站允许,您可使用 ExternalInterface 类获取确切 URL.尽管如此,允许第三方视频播放器的一些 ...
- 深入css中的margin
深入css中的margin 第一:margin-top css代码(元素没有任何定位的情况下,并且元素默认为block) <style type="text/css"> ...
- 针对应用程序池“xxxxxx”的模板永久性缓存初始化失败,解决方法
日志名称: Application 来源: Active Server Pages 日期: 2014-11-22 9:09:39 事件 I ...