2019牛客暑期多校訓練營(第八場)Flower Dance

2019牛客暑期多校訓練營(第八場)Flower Dance
** 題意: ** 給nn個點 mm條邊,每條邊有一個權值區間,表示能通過這個區間的 值的範圍,問從11nn可以通過的權值有多少個。
** 題解: **

1.DFS線段樹+離散化+並查集

這個線段樹,其實也不能算是個正常的線段樹,他build 的之後就沒啥用了,沒有更新和查詢.。。直接在線段樹上dfs,首先把權值離散化,然後存入線段樹中,線段樹每個節點表示,區間[l,r],中有哪些邊,這樣每次深搜下去,經過的邊用並查集維護起來,表示哪些點是聯通的,然後如果,1n聯通的話就更新權值。這題有回溯,就有拆邊,所以並查集要保存路徑,而且要加按秩合併的優化,不然會超時。
** 寫離散化線段樹儘量保存 (l,r] 左開右閉的區間值,保存[l,r] 的區間會出問題**

#include "bits/stdc++.h"

using namespace std;
typedef long long LL;
typedef unsigned long long uLL;
typedef pair<int, int> P;
#define VNAME(value) (#value)
#define bug printf("*********\n");
#define debug(x) cout<<"["<<VNAME(x)<<" = "<<x<<"]"<<endl;
#define mid ((l + r) >> 1)
#define chl 2 * k + 1
#define chr 2 * k + 2
#define lson l, mid, chl
#define rson mid, r, chr
#define eb(x) emplace_back(x)
#define pb(x) emplace_back(x)
#define mem(a, b) memset(a, b, sizeof(a));

const LL mod = (LL) 1e9 + 7;
const int maxn = (int) 1e6 + 5;
const LL INF = 0x7fffffff;
const LL inf = 0x3f3f3f3f;
const double eps = 1e-8;

#ifndef ONLINE_JUDGE
clock_t prostart = clock();
#endif

void f() {
#ifndef ONLINE_JUDGE
    freopen("../data.in", "r", stdin);
#endif
}

//typedef __int128 LLL;

template<typename T>
void read(T &w) {//讀入
    char c;
    while (!isdigit(c = getchar()));
    w = c & 15;
    while (isdigit(c = getchar()))
        w = w * 10 + (c & 15);
}

template<typename T>
void output(T x) {
    if (x < 0)
        putchar('-'), x = -x;
    int ss[55], sp = 0;
    do
        ss[++sp] = x % 10;
    while (x /= 10);
    while (sp)
        putchar(48 + ss[sp--]);
}

struct edge {
    int u, v, l, r;
} eg[maxn];


vector<int> v;

int get(int x) {
    return lower_bound(v.begin(), v.end(), x) - v.begin() + 1;
}

int n, m;
vector<int> dat[maxn];

void build(int l, int r, int k, int a, int b, int x) {
    if (l == a && b == r) {
        dat[k].emplace_back(x);
        return;
    }
    if (b <= mid) {
        build(lson, a, b, x);
    } else if (a >= mid) {
        build(rson, a, b, x);
    } else {
        build(lson, a, mid, x);
        build(rson, mid, b, x);
    }
}

vector<int> d[maxn];
int ans = 0;
int par[maxn];

int find(int x) {
    return (par[x] == x) ? x : find(par[x]);
}

int rk[maxn];

void unit(int x, int y, int dep) {
    x = find(x);
    y = find(y);
    if (x != y) {
        if (rk[x] < rk[y])swap(x, y);
        par[y] = x;
        d[dep].emplace_back(y);
        if (rk[x] == rk[y])rk[x]++;
    }
}

void dfs(int l, int r, int k, int dep) {
    d[dep].clear();
    for (auto au:dat[k]) {
        unit(eg[au].u, eg[au].v, dep);
    }
    if (find(1) == find(n)) {
        ans += v[r - 1] - v[l - 1];
    } else if (r != l + 1) {
        dfs(lson, dep + 1);
        dfs(rson, dep + 1);
    }
    for (auto au:d[dep]) {
        par[au] = au;
    }
}

int main() {
    f();
    read(n);
    read(m);
    for (int i = 0; i <= n; i++)par[i] = i;
    for (int i = 0; i < m; i++) {
        read(eg[i].u);
        read(eg[i].v);
        read(eg[i].l);
        read(eg[i].r);
        v.emplace_back(eg[i].l);
        v.emplace_back(eg[i].r + 1);
    }
    sort(v.begin(), v.end());
    v.erase(unique(v.begin(), v.end()), v.end());
    int mx = v.size();
    for (int i = 0; i < m; i++) {
        build(1, mx, 1, get(eg[i].l), get(eg[i].r + 1), i);
    }
    dfs(1, mx, 1, 0);
    output(ans);
    puts("");

#ifndef ONLINE_JUDGE
    cout << "運行時間:" << 1.0 * (clock() - prostart) / CLOCKS_PER_SEC << endl;
#endif
    return 0;
}

LCT+最小生成樹 挖個坑,懶得學splay

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章