【BZOJ 2594】【WC 2006】水管局长数据加强版

离线后倒过来做,这样就跟魔法森林差不多了,缩边为点就可以统计边的权值了。

1A真是爽,可惜常数炸上了天,这是滥用stl容器和无脑link,cut的后果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
#include<map>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 100003;
const int M = 1000003;
void read(int &k) {
    k = 0; int fh = 1; char c = getchar();
    for(; c < '0' || c > '9'; c = getchar())
        if (c == '-') fh = -1;
    for(; c >= '0' && c <= '9'; c = getchar())
        k = (k << 1) + (k << 3) + c - '0';
    k = k * fh;
}
 
struct node *null;
struct node {
    node *ch[2], *fa;
    int mx, mxid, d, id;
    short rev;
    bool pl() {return fa->ch[1] == this;}
    bool check() {return fa == null || (fa->ch[0] != this && fa->ch[1] != this);}
    void push() {if (rev) {rev = 0; swap(ch[0], ch[1]); ch[0]->rev ^= 1; ch[1]->rev ^= 1;}}
    void count() {
        mxid = id; mx = d;
        if (ch[0]->mx > mx) {mx = ch[0]->mx; mxid = ch[0]->mxid;}
        if (ch[1]->mx > mx) {mx = ch[1]->mx; mxid = ch[1]->mxid;}
    }
    void setc(node *r, bool c) {ch[c] = r; r->fa = this;}
} pool[N + M];
 
struct Quee{int op, u, v;} Q[N];
struct Data{int u, v, e;} E[M];
struct maa{
    int u, v;
    bool operator < (const maa data) const
        {return u == data.u ? v < data.v : u < data.u;}
};
bool cmp(Data A, Data B) {return A.e < B.e;}
map <maa, int> ma;
bool cannot[M];
namespace LCT {
    int fa[N];
    int find(int x) {return fa[x] == x ? x : (fa[x] = find(fa[x]));}
    void rotate(node *r) {
        node *f = r->fa;
        bool c = r->pl();
        if (f->check()) r->fa = f->fa;
        else f->fa->setc(r, f->pl());
        f->setc(r->ch[!c], c);
        r->setc(f, !c);
        f->count();
    }
    void update(node *r) {if (!r->check()) update(r->fa); r->push();}
    void splay(node *r) {
        update(r);
        for(; !r->check(); rotate(r))
            if (!r->fa->check()) rotate(r->pl() == r->fa->pl() ? r->fa : r);
        r->count();
    }
    node *access(node *r) {node *y = null; for(; r != null; y = r, r = r->fa) splay(r), r->ch[1] = y; return y;}
    void changert(node *r) {access(r)->rev ^= 1; splay(r);}
    void link(node *r, node *t) {changert(r); r->fa = t;}
    void cut(node *r, node *t) {changert(r); access(t); splay(t); t->ch[0]->fa = null; t->ch[0] = null;}
    node *findrt(node *r) {access(r); splay(r); while (r->ch[0] != null) r = r->ch[0]; return r;}
     
    void newnode(int k, int num) {
        pool[k].ch[0] = pool[k].ch[1] = pool[k].fa = null;
        pool[k].id = pool[k].mxid = k; pool[k].d = pool[k].mx = num; pool[k].rev = 0;
    }
    int A[N];
    void Build(int n, int m, int q) {
        null = &pool[0];
        null->ch[0] = null->ch[1] = null->fa = null;
        null->id = null->d = null->mx = null->mxid = null->rev = 0;
        int u, v, e;
        for(int i = 1; i <= n; ++i)  newnode(i, 0);
        for(int i = 1; i <= m; ++i) {
            read(u); read(v); read(e);
            if (u > v) swap(u, v);
            E[i] = (Data) {u, v, e};
        }
        sort(E + 1, E + m + 1, cmp);
        for(int i = 1; i <= m; ++i) {
            ma[(maa) {E[i].u, E[i].v}] = i;
            newnode(i + n, E[i].e);
        }
        for(int i = 1; i <= q; ++i) {
            read(Q[i].op); read(Q[i].u); read(Q[i].v);
            if (Q[i].u > Q[i].v) swap(Q[i].u, Q[i].v);
            if (Q[i].op == 2) cannot[ma[(maa) {Q[i].u, Q[i].v}]] = 1;
        }
        node *tox, *toy, *toe;
        int cnt = 0, x, y, fx, fy;
        for(int i = 1; i <= n; ++i) fa[i] = i;
        for(int i = 1; i <= m; ++i) {
            x = E[i].u; y = E[i].v;
            fx = find(x); fy = find(y);
            if (fx != fy && !cannot[e = ma[(maa) {x, y}]]) {
                ++cnt;
                fa[fx] = fy;
                tox = &pool[x]; toy = &pool[y]; toe = &pool[e + n];
                link(tox, toe); link(toy, toe);
                if (cnt == n - 1) break;
            }
        }
        cnt = 0;
        for(int i = q; i >= 1; --i) {
            if (Q[i].op == 1) {
                tox = &pool[Q[i].u]; toy = &pool[Q[i].v];
                changert(tox); access(toy); splay(toy);
                A[++cnt] = toy->mx;
            } else {
                tox = &pool[Q[i].u]; toy = &pool[Q[i].v];
                e = ma[(maa) {Q[i].u, Q[i].v}];
                changert(tox); access(toy); splay(toy);
                if (E[e].e < toy->mx) {
                    u = toy->mxid - n;
                    tox = &pool[E[u].u]; toy = &pool[E[u].v]; toe = &pool[u + n];
                    cut(tox, toe); cut(toy, toe);
                    tox = &pool[Q[i].u]; toy = &pool[Q[i].v]; toe = &pool[e + n];
                    link(tox, toe); link(toy, toe);
                }
            }
        }
        for(int i = cnt; i; --i) printf("%d\n", A[i]);
    }
}
 
int n, m, q;
int main() {
    read(n); read(m); read(q);
    LCT::Build(n, m, q);
    return 0;
}

模板一定不能写残啊,想起一个月前Round1Day1调LCT的模板调了4h,查出各种手残的错误QAQ然而并没有什么用。

posted @   abclzr  阅读(175)  评论(0)    收藏  举报
编辑推荐:
· 如何统计不同电话号码的个数?—位图法
· C#高性能开发之类型系统:从 C# 7.0 到 C# 14 的类型系统演进全景
· 从零实现富文本编辑器#3-基于Delta的线性数据结构模型
· 记一次 .NET某旅行社酒店管理系统 卡死分析
· 长文讲解 MCP 和案例实战
阅读排行:
· C#高性能开发之类型系统:从 C# 7.0 到 C# 14 的类型系统演进全景
· 管理100个小程序-很难吗
· 基于Blazor实现的运输信息管理系统
· 微信支付功能的设计实现与关键实践(UniApp+Java)全代码
· 用c#从头写一个AI agent,实现企业内部自然语言数据统计分析
点击右上角即可分享
微信分享提示