2019牛客暑期多校訓練營(第八場)Flower Dance
** 題意: ** 給個點 條邊,每條邊有一個權值區間,表示能通過這個區間的 值的範圍,問從到可以通過的權值有多少個。
** 題解: **
1.DFS線段樹+離散化+並查集
這個線段樹,其實也不能算是個正常的線段樹,他build
的之後就沒啥用了,沒有更新和查詢.。。直接在線段樹上dfs
,首先把權值離散化,然後存入線段樹中,線段樹每個節點表示,區間[l,r]
,中有哪些邊,這樣每次深搜下去,經過的邊用並查集維護起來,表示哪些點是聯通的,然後如果,1
和n
聯通的話就更新權值。這題有回溯,就有拆邊,所以並查集要保存路徑,而且要加按秩合併
的優化,不然會超時。
** 寫離散化線段樹儘量保存 (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;
}