题目链接

题意:

给一棵树。有边权

1、询问路径的边权和

2、询问沿着路径的第k个点标。

思路:lct裸题。

#include <iostream>
#include <fstream>
#include <string>
#include <time.h>
#include <vector>
#include <map>
#include <queue>
#include <algorithm>
#include <stack>
#include <cstring>
#include <cmath>
#include <set>
#include <vector>
using namespace std;
template <class T>
inline bool rd(T &ret) {
char c; int sgn;
if (c = getchar(), c == EOF) return 0;
while (c != '-' && (c<'0' || c>'9')) c = getchar();
sgn = (c == '-') ? -1 : 1;
ret = (c == '-') ? 0 : (c - '0');
while (c = getchar(), c >= '0'&&c <= '9') ret = ret * 10 + (c - '0');
ret *= sgn;
return 1;
}
template <class T>
inline void pt(T x) {
if (x <0) {
putchar('-');
x = -x;
}
if (x>9) pt(x / 10);
putchar(x % 10 + '0');
}
typedef long long ll;
typedef pair<int, int> pii;
const int N = 30005;
const int inf = 10000000;
struct Node *null;
struct Node{
Node *fa, *ch[2];
int size;
int val, ma, sum, id;
bool rev;
inline void put(){
printf("%d:id, %d,%d,%d (%d,%d) fa:%d \n", id, val, ma, sum, ch[0]->id, ch[1]->id, fa->id);
}
void debug(Node *x){
if (x == null)return;
x->put();
if (x->ch[0] != null)putchar('L'), debug(x->ch[0]);
if (x->ch[1] != null)putchar('r'), debug(x->ch[1]);
} inline void clear(int _val, int _id){
fa = ch[0] = ch[1] = null;
size = 1;
rev = 0;
id = _id;
val = ma = sum = _val;
}
inline void add_val(int _val){
val += _val;
sum += _val;
ma = max(ma, val);
}
inline void push_up(){
size = 1 + ch[0]->size + ch[1]->size; sum = ma = val;
if (ch[0] != null) {
sum += ch[0]->sum;
ma = max(ma, ch[0]->ma);
}
if (ch[1] != null){
sum += ch[1]->sum;
ma = max(ma, ch[1]->ma);
}
}
inline void push_down(){
if (rev){
flip(); ch[0]->rev ^= 1; ch[1]->rev ^= 1;
}
}
inline void setc(Node *p, int d){
ch[d] = p;
p->fa = this;
}
inline bool d(){
return fa->ch[1] == this;
}
inline bool isroot(){
return fa == null || fa->ch[0] != this && fa->ch[1] != this;
}
inline void flip(){
if (this == null)return;
swap(ch[0], ch[1]);
rev ^= 1;
}
inline void go(){//从链头開始更新到this
if (!isroot())fa->go();
push_down();
}
inline void rot(){
Node *f = fa, *ff = fa->fa;
int c = d(), cc = fa->d();
f->setc(ch[!c], c);
this->setc(f, !c);
if (ff->ch[cc] == f)ff->setc(this, cc);
else this->fa = ff;
f->push_up();
}
inline Node*splay(){
go();
while (!isroot()){
if (!fa->isroot())
d() == fa->d() ? fa->rot() : rot();
rot();
}
push_up();
return this;
}
inline Node* access(){//access后this就是到根的一条splay,而且this已经是这个splay的根了
for (Node *p = this, *q = null; p != null; q = p, p = p->fa){
p->splay()->setc(q, 1);
p->push_up();
}
return splay();
}
inline Node* find_root(){
Node *x;
for (x = access(); x->push_down(), x->ch[0] != null; x = x->ch[0]);
return x;
}
void make_root(){
access()->flip();
}
void cut(){//把这个点的子树脱离出去
access();
ch[0]->fa = null;
ch[0] = null;
push_up();
}
void cut(Node *x){
if (this == x || find_root() != x->find_root())return;
else {
x->make_root();
cut();
}
}
void link(Node *x){
if (find_root() == x->find_root())return;
else {
make_root(); fa = x;
}
}
};
Node pool[N], *tail;
Node *node[N], *ee[N];
int n, q;
void debug(Node *x){
if (x == null)return;
x->put();
debug(x->ch[0]);
debug(x->ch[1]);
}
inline int ask(Node *x, Node *y){
x->access();
// for (int i = 1; i <= n; i++)debug(node[i]), putchar('\n');
for (x = null; y != null; x = y, y = y->fa){
y->splay();
// for (int i = 1; i <= n; i++)debug(node[i]), putchar('\n');
if (y->fa == null)return y->ch[1]->sum + x->sum;
y->setc(x, 1);
y->push_up();
}
}
inline Node* get_kth(Node *x, int k){
while (x->ch[0]->size + 1 != k){
if (x->ch[0]->size >= k)
x = x->ch[0];
else k -= x->ch[0]->size + 1, x = x->ch[1];
}
return x;
}
inline int query_kth(Node *x, Node *y, int k){
x->access();
for (x = null; y != null; x = y, y = y->fa){
y->splay();
if (y->fa == null){
if (k == y->ch[1]->size + 1)return y->id;
if (k < y->ch[1]->size + 1)return get_kth(y->ch[1], y->ch[1]->size - k + 1)->id;
return get_kth(x, k - y->ch[1]->size - 1)->id;
}
y->setc(x, 1);
y->push_up();
}
}
struct Edge{
int from, to, dis, id, nex;
}edge[N << 1];
int head[N], edgenum;
void add(int u, int v, int dis, int id){
Edge E = { u, v, dis, id, head[u] };
edge[edgenum] = E;
head[u] = edgenum++;
}
bool vis[N];
void bfs(){
fill(vis + 1, vis + 1 + n, false);
queue<int>q;
q.push(1);
vis[1] = true;
while (!q.empty()){
int u = q.front(); q.pop();
for (int i = head[u]; ~i; i = edge[i].nex){
int v = edge[i].to;
if (vis[v])continue;
vis[v] = true;
q.push(v);
ee[edge[i].id] = node[v];
node[v]->val = edge[i].dis;
node[v]->push_up();
node[v]->fa = node[u];
}
}
}
int main(){
int T; rd(T);
while (T--){
rd(n);
fill(head + 1, head + n + 1, -1); edgenum = 0;
tail = pool;
null = tail++; null->clear(-inf, 0);
null->size = 0; null->sum = 0;
for (int i = 1; i <= n; i++) {
node[i] = tail++;
node[i]->clear(0, i);
}
for (int i = 1, u, v, d; i < n; i++){
rd(u); rd(v); rd(d);
add(u, v, d, i);
add(v, u, d, i);
}
bfs();
char str[10]; int u, v, k;
while (true){
scanf("%s", str);
if (str[1] == 'O')break;
rd(u); rd(v);
if (str[0] == 'D')pt(ask(node[u], node[v])), putchar('\n');
else {
rd(k);
pt(query_kth(node[u], node[v], k)); putchar('\n');
}
}
puts("");
}
return 0;
}
/*
1
6
1 2 1
2 4 1
2 5 2
1 3 1
3 6 2
DIST 4 6
KTH 4 6 4
KTH 6 5 4
DIST 2 5 */

SPOJ QTREE2 lct的更多相关文章

  1. SPOJ - OTOCI LCT

    OTOCI Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://acm.hust.edu.cn/vjudge/problem/viewProblem. ...

  2. SPOJ QTREE4 lct

    题目链接 这个题已经处于花式tle了,改版后的spoj更慢了.. tle的话就多交几把... #include <iostream> #include <fstream> #i ...

  3. SPOJ QTREE2 Query on a tree II

    传送门 倍增水题…… 本来还想用LCT做的……然后发现根本不需要 //minamoto #include<bits/stdc++.h> using namespace std; #defi ...

  4. SPOJ QTREE3 lct

    题目链接 题意: 给定n个点 q个询问 以下n-1行给出树边,点有黑或白色.初始化为白色 以下q行: 询问有2种: 1. 0 x 把x点黑变白,白变黑 2.1 x 询问Path(1,x)路径上第一个黑 ...

  5. 【SPOJ QTREE2】QTREE2 - Query on a tree II(LCA)

    You are given a tree (an undirected acyclic connected graph) with N nodes, and edges numbered 1, 2, ...

  6. SPOJ QTREE2 (LCA - 倍增 在线)

    You are given a tree (an undirected acyclic connected graph) with N nodes, and edges numbered 1, 2, ...

  7. SPOJ QTREE5 lct

    题目链接 对于每一个节点,记录这个节点所在链的信息: ls:(链的上端点)距离链内部近期的白点距离 rs:(链的下端点)距离链内部近期的白点距离 注意以上都是实边 虚边的信息用一个set维护. set ...

  8. 【SPOJ - QTREE2】树链剖分

    http://acm.hust.edu.cn/vjudge/problem/19960 题意: 有一棵N个节点的树(1<=N<=10000),N-1条边,边的编号为1~N-1,每条边有一个 ...

  9. SPOJ QTREE6 lct

    题目链接 岛娘出的题.还是比較easy的 #include <iostream> #include <fstream> #include <string> #inc ...

随机推荐

  1. django-registration (1048, “Column 'last_login' cannot be null”)

    Go to your database (MySQL Terminal): $ mysql mysql> SELECT * FROM django_migrations; If you see ...

  2. 简单了解了下SEO与SEM的机制

    SEO:搜索引擎优化SEM:搜索引擎营销 SEO排名机制:搜索引擎蜘蛛 权重 算法 排名规则 搜索引擎提交入口: 1.百度搜索网站登入口 2.Google网站登入口 3.360搜索引擎登入入口 4.搜 ...

  3. Windows提高_2.1第一部分:线程

    第一部分:线程 什么是线程? 线程其实可以理解为一段正在执行中的代码,它最少由一个线程内核对象和一个栈组成. 线程之间是没有从属关系的,同一进程下的所有线程都可以访问进程内的所有内容. 主线程其实是创 ...

  4. c++类简介

    C++类(Class)总结   一.C++类的定义     C++中使用关键字 class 来定义类, 其基本形式如下:class 类名{ public: //行为或属性  protected: // ...

  5. 梦想CAD控件 2018.10.15更新

    下载地址: http://www.mxdraw.com/ndetail_10105.html 1. 完善com接口的ToCurves函数,转换CAD文字,多行文字到曲线 2. 修改DrawImage接 ...

  6. ThinkPHP---thinkphp完善站内信功能

    [一]收件箱 分析 控制器:EmailController.class.php 方法:recBox(全称receive box收件箱) 模板文件:recBox.html 分步操作: 第一步:创建方法r ...

  7. 00The C Programming Language

    The C Programming Language C语言是一门面向过程.抽象化的通用程序设计语言,广泛应用于底层开发.C语言能以简易的方式编译.处理低级存储器.C语言是仅产生少量的机器语言以及不需 ...

  8. 出生年 (15 分) C解法

    出生年 以上是新浪微博中一奇葩贴:"我出生于1988年,直到25岁才遇到4个数字都不相同的年份."也就是说,直到2013年才达到"4个数字都不相同"的要求.本题 ...

  9. CF 429B B.Working out (四角dp)

    题意: 两个人一个从左上角一个从左下角分别开始走分别走向右下角和右上角,(矩阵每个格子有数)问到达终点后可以得到的最大数是多少,并且条件是他们两个相遇的时候那个点的数不能算 思路: 首先这道题如果暴力 ...

  10. 爬虫实战(一) 用Python爬取百度百科

    最近博主遇到这样一个需求:当用户输入一个词语时,返回这个词语的解释 我的第一个想法是做一个数据库,把常用的词语和词语的解释放到数据库里面,当用户查询时直接读取数据库结果 但是自己又没有心思做这样一个数 ...