SPOJ QTREE2 lct

题目链接

题意:

给一棵树。有边权

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

*/
时间: 2024-10-06 09:53:57

SPOJ QTREE2 lct的相关文章

SPOJ QTREE2 lct裸题

题目链接 题意: 给一棵树,有边权 1.询问路径的边权和 2.询问沿着路径的第k个点标. 思路:lct裸题. #include <iostream> #include <fstream> #include <string> #include <time.h> #include <vector> #include <map> #include <queue> #include <algorithm> #inclu

SPOJ QTREE2 Query on a tree II

Query on a tree II Time Limit: 2000ms Memory Limit: 262144KB This problem will be judged on SPOJ. Original ID: QTREE264-bit integer IO format: %lld      Java class name: Main You are given a tree (an undirected acyclic connected graph) with N nodes,

SPOJ QTREE3 lct裸题

题目链接 题意: 给定n个点 q个询问 下面n-1行给出树边,点有黑或白色,初始化为白色 下面q行: 询问有2种: 1. 0 x 把x点黑变白,白变黑 2.1 x 询问Path(1,x)路径上第一个黑点的点标, 若不存在黑点则输出-1 思路: lct裸题 #include <iostream> #include <fstream> #include <string> #include <time.h> #include <vector> #inc

SPOJ - OTOCI LCT

OTOCI Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=18141 Description Some time ago Mirko founded a new tourist agency named "Dreams of Ice". The agency purchased N icy islands near the S

SPOJ QTREE4 lct

题目链接 这个题已经处于花式tle了,改版后的spoj更慢了.. tle的话就多交几把... #include <iostream> #include <fstream> #include <string> #include <time.h> #include <vector> #include <map> #include <queue> #include <algorithm> #include <s

SPOJ QTREE5 lct裸题

题目链接 对于每个节点,记录这个节点所在链的信息: ls:(链的上端点)距离链内部最近的白点距离 rs:(链的下端点)距离链内部最近的白点距离 注意以上都是实边 虚边的信息用一个set维护. set维护的是对于每个不是链上,但是this的子树,那些子树中距离this最近的白点距离. #include <stdio.h> #include <string.h> #include <set> #include <algorithm> #include <i

【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, 3...N-1. Each edge has an integer value assigned to it, representing its length. We will ask you to perfrom some instructions of the following form: D

SPOJ QTREE6 lct

题目链接 岛娘出的题.还是比較easy的 #include <iostream> #include <fstream> #include <string> #include <time.h> #include <vector> #include <map> #include <queue> #include <algorithm> #include <stack> #include <cstr

【LCA】SPOJ QTREE2

You are given a tree (an undirected acyclic connected graph) with N nodes, and edges numbered 1, 2, 3...N-1. Each edge has an integer value assigned to it, representing its length. We will ask you to perfrom some instructions of the following form: D