HDU5002 Tree(LCT)
今天做了一道LCT模板题之后忽然间好像记起来LCT的模板怎么用了,于是就把上次网络赛的一道LCT补一下。典型的删边,加边操作,还有路径加和路径set为一个数。维护的是路径第二大以及它有多少个,后来想想其实确实是挺好写的,就是维护最大值以及次大值,然后upd的时候把儿子合并回去就好了,当时觉得不会做实在是想太多了。
#pragma warning(disable:4996)
#include <iostream>
#include <cstring>
#include <string>
#include <cstdio>
#include <vector>
#include <algorithm>
#include <map>
using namespace std; #define ll long long
#define maxn 200000
#define INF 0x3f3f3f3f
#define INP INF+1
#define MP make_pair void merge(int mxx[2], int nxx[2], int pval, int pnum)
{
if (pval>mxx[0]){
mxx[1] = mxx[0]; nxx[1] = nxx[0];
mxx[0] = pval; nxx[0] = pnum;
}
else if (pval == mxx[0]){
nxx[0] += pnum;
}
else if (pval>mxx[1]){
mxx[1] = pval; nxx[1] = pnum;
}
else if(pval==mxx[1]){
nxx[1] += pnum;
}
} struct Node
{
Node *p, *ch[2];
bool rev;
int val;
int mx[2], num[2];
int add, cov;
int size;
bool isRoot;
Node *fa;
Node(){
val = 0; rev = 0;
add = 0; cov = INP;
mx[0] = mx[1] = -INF;
num[0] = num[1] = 0;
size = 0;
}
void setc(Node *c, int d){
ch[d] = c;
c->p = this;
}
bool d(){
return p->ch[1] == this;
}
void upd(){
size = ch[0]->size + ch[1]->size + 1;
mx[0] = ch[0]->mx[0]; num[0] = ch[0]->num[0];
mx[1] = ch[0]->mx[1]; num[1] = ch[0]->num[1];
merge(mx, num, val, 1);
merge(mx, num, ch[1]->mx[0], ch[1]->num[0]);
merge(mx, num, ch[1]->mx[1], ch[1]->num[1]);
}
void revIt(){
rev ^= 1;
swap(ch[0], ch[1]);
}
void addIt(int vx){
add += vx;
val += vx;
if (mx[0] != -INF) mx[0] += vx;
if (mx[1] != -INF) mx[1] += vx;
}
void setIt(int vx){
add = 0;
cov = vx;
val = vx;
mx[0] = vx; num[0] = size;
mx[1] = -INF; num[1] = 0;
}
void relax();
void setRoot(Node *f);
}Tnull, *null = &Tnull; void Node::setRoot(Node *f){
fa = f;
isRoot = true;
p = null;
} void Node::relax(){
if (cov != INP){
for (int i = 0; i<2; ++i){
if (ch[i] != null) ch[i]->setIt(cov);
}
cov = INP;
}
if (add != 0){
for (int i = 0; i < 2; i++){
if (ch[i] != null) ch[i]->addIt(add);
}
add = 0;
}
if (rev){
for (int i = 0; i < 2; i++){
if (ch[i] != null) ch[i]->revIt();
}
rev = 0;
}
} Node mem[maxn], *C = mem; Node *make(int v){
C->size=1;
C->val = v;
C->rev = 0; C->add = 0;
C->cov = INP;
C->mx[0] = v; C->num[0] = 1;
C->mx[1] = -INF; C->num[1] = 0;
C->ch[0] = C->ch[1] = null; C->isRoot = true;
C->p = null;
C->fa = null;
return C++;
} void rot(Node *t){
Node *p = t->p;
p->relax();
t->relax();
bool d = t->d();
p->p->setc(t, p->d());
p->setc(t->ch[!d], d);
t->setc(p, !d);
p->upd();
if (p->isRoot){
p->isRoot = false;
t->isRoot = true;
t->fa = p->fa;
}
} void pushTo(Node*t) {
static Node*stk[maxn]; int top = 0;
while (t != null) {
stk[top++] = t;
t = t->p;
}
for (int i = top - 1; i >= 0; --i) stk[i]->relax();
} void splay(Node*u, Node*f = null) {
pushTo(u);
while (u->p != f) {
if (u->p->p == f)
rot(u);
else
u->d() == u->p->d() ? (rot(u->p), rot(u)) : (rot(u), rot(u));
}
u->upd();
} Node *v[maxn];
vector<int> E[maxn];
int n, nQ; int que[maxn], fa[maxn], qh = 0, qt = 0;
int wht[maxn]; void bfs()
{
qh = qt = 0;
que[qt++] = 1;
fa[1] = -1;
while (qh < qt){
int u = que[qh++];
for (int i = 0; i < E[u].size(); i++){
int e = E[u][i];
if (e != fa[u]){
fa[e] = u;
v[e]->fa = v[u];
que[qt++] = e;
}
}
}
} Node *expose(Node *u)
{
Node *v;
for (v = null; u != null; v = u, u = u->fa){
splay(u);
u->ch[1]->setRoot(u);
u->setc(v, 1);
v->fa = u;
}
return v;
} void makeRoot(Node *u)
{
expose(u);
splay(u);
u->revIt();
} void addEdge(Node *u, Node *v)
{
makeRoot(v);
v->fa = u;
} void delEdge(Node *u, Node *v)
{
makeRoot(u);
expose(v); splay(u); u->setc(null, 1); u->upd();
v->setRoot(null);
} void addPath(Node *u, Node *v, int ax)
{
makeRoot(u);
expose(v);
splay(v);
v->addIt(ax);
} void setPath(Node *u, Node *v, int ax)
{
makeRoot(u);
expose(v);
splay(v);
v->setIt(ax);
} pair<int, int> queryPath(Node *u, Node *v){
makeRoot(u);
expose(v);
splay(v);
return MP(v->mx[1], v->num[1]);
} Node *find_root(Node *u)
{
expose(u); splay(u);
while (u->ch[0] != null){
u = u->ch[0];
}
splay(u); return u;
} int main()
{
int T; cin >> T;int ca=0;
while (T--)
{
C = mem;
scanf("%d%d", &n, &nQ);
for (int i = 1; i <= n; i++){
scanf("%d", wht + i);
v[i] = make(wht[i]);
}
for (int i = 0; i <= n; i++) E[i].clear();
int ui, vi;
for (int i = 0; i < n - 1; i++){
scanf("%d%d", &ui, &vi);
E[ui].push_back(vi); E[vi].push_back(ui);
}
bfs();
int cmd, xi, yi, ai, bi;
Node *nx, *ny, *na, *nb;
printf("Case #%d:\n",++ca);
while (nQ--){
scanf("%d", &cmd);
if (cmd == 1) scanf("%d%d%d%d", &xi, &yi, &ai, &bi);
else if (cmd == 2 || cmd == 3) scanf("%d%d%d", &ai, &bi, &xi);
else scanf("%d%d", &ai, &bi); if (cmd == 1){
nx = v[xi]; ny = v[yi];
na = v[ai]; nb = v[bi];
delEdge(nx, ny);
addEdge(na, nb);
}
else if (cmd == 2){
nx = v[ai]; ny = v[bi];
setPath(nx, ny, xi);
}
else if (cmd == 3){
nx = v[ai]; ny = v[bi];
addPath(nx, ny, xi);
}
else{
nx = v[ai]; ny = v[bi];
pair<int, int> ans = queryPath(nx, ny);
if (ans.first <= -INF) printf("ALL SAME\n");
else printf("%d %d\n", ans.first, ans.second);
}
}
}
return 0;
}
HDU5002 Tree(LCT)的更多相关文章
- HDU 5002 Tree LCT 区间更新
Tree Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://acm.hust.edu.cn/vjudge/contest/view.action?c ...
- hdu5398 GCD Tree(lct)
转载请注明出处: http://www.cnblogs.com/fraud/ ——by fraud GCD Tree Time Limit: 5000/2500 MS (Java/O ...
- BZOJ 3282: Tree( LCT )
LCT.. -------------------------------------------------------------------------------- #include<c ...
- BZOJ 2631: tree( LCT )
LCT...略麻烦... -------------------------------------------------------------------------------- #inclu ...
- [bzoj3282]Tree (lct)
昨天看了一天的lct..当然幸好最后看懂了(也许吧..) 论善良学长的重要性T_T,老司机带带我! 这题主要是删边的时候还要判断一下..蒟蒻一开始天真的以为存在的边才能删结果吃了一发wa... 事实是 ...
- Link-Cut Tree(LCT)&TopTree讲解
前言: Link-Cut Tree简称LCT是解决动态树问题的一种数据结构,可以说是我见过功能最强大的一种树上数据结构了.在此与大家分享一下LCT的学习笔记.提示:前置知识点需要树链剖分和splay. ...
- 动态树Link-cut tree(LCT)总结
动态树是个好玩的东西 LCT题集 预备知识 Splay 树链剖分(好像关系并不大) 动态树(Link-cut tree) 先搬dalao博客 什么是LCT? 动态树是一类要求维护森林的连通性的题的总称 ...
- 洛谷P3690 [模板] Link Cut Tree [LCT]
题目传送门 Link Cut Tree 题目背景 动态树 题目描述 给定n个点以及每个点的权值,要你处理接下来的m个操作.操作有4种.操作从0到3编号.点从1到n编号. 0:后接两个整数(x,y),代 ...
- 浅谈Link-Cut Tree(LCT)
0XFF 前言&概念 Link-Cut Tree 是一种用来维护动态森林连通性的数据结构,适用于动态树问题.它采用类似树链剖分的轻重边路径剖分,把树边分为实边和虚边,并用 Splay 来维护每 ...
随机推荐
- DrawTool多重笔之前奏 => 通过InkAnalyzer实现图形识别
这里要介绍的是通过InkAnalyzer来实现简单图形的识别,例如圆,椭圆,正方形,三角形等,当然你也可以通过扩展来实现自定义图形的识别,在使用InkAnalyzer前,你需要引用IAWinFX.dl ...
- JS对文本框值的判断
JS判断只能是数字和小数点(摘录自其它资料,在此发表只为个人以后使用查找方便) 1.文本框只能输入数字(不包括小数点) <input onkeyup="this.value=this. ...
- qtp 设置等待时间
1.file->settings->run .默认的时间是20 秒 2. browser("browser").Navigate http://www.baidu.co ...
- 什么是O/R Mapping(ORM)
ORM,即Object-Relationl Mapping,它的作用是在关系型数据库和对象之间作一个映射,这样,我们在具体的操作数据库的时候,就不需要再去和复杂的SQL语句打交道,只要像平时操作对象一 ...
- iOS 初级数据持久化
数据持久化 什么是数据持久化? 数据的永久存储 为什么要做数据持久化::存储在内存中的数据,程序关闭,内存释放,数据丢失,这种数据是临时的 数据持久化的本质:数据保存成文件,存储到程序的沙盒中 一.沙 ...
- Entity Framework 泛型使用
因为增删改查是我们常用到的方法,我们不可能每个数据模型都去完成增删改查,这样的办法太笨拙了.我们可以写个父类(包含增删改查),然后让所有的数据模型类继承该父类.那就要求我们的父类必须使用泛型来实现. ...
- Jsp实现筛选并压缩文件批量下载
Jsp实现筛选并压缩文件批量下载 首先明确一下需求,网页端点击一下button,传递特定的参数到download.jsp网页,筛选文件,对过滤得到的文件进行压缩,然后返回前端一个压缩包下载. 以下的代 ...
- VC++编程中为程序加入启动画面功能
如何为自己的程序加入启动画面 观察我们平常使用的软件,当我们双击软件的时候,会在主界面出现前,先行出现一个启动画面,由于前一阵子写了一个基于对话框的程序,亲自实验了下,今天就为大家简单的介绍下,在我 ...
- Sqrt(x)
Implement int sqrt(int x). Compute and return the square root of x. 参考:http://standalone.iteye.com/b ...
- c++中的virtual函数,即虚函数
c++中的虚函数主要是用来实现多态的,虽然都同时指向父类的实例.但调用的确实子类的函数,这个有点像java的接口和实现的关系了.一个接口有多种实现,一个接口对象调用的是哪个实现的方法,这个就是多态了 ...