Cattle off more school eighth field E Explorer (right-left opening and closing segment tree + retractable disjoint-set) solution to a problem

Meaning of the questions:

There \ (n \) points constitute an undirected graph, each side has \ (L_i, R_i \) represents this edge can only allow number \ (L_i \ dots R_i \) by the people, and now you ask most several people from \ (1 \) went \ (the n-\) .

Ideas:

We can enumerate each number, and then take a look through this number all the edges can form a map so that \ (1 \) went \ (the n-\) , but the point is clear that the enumeration is not realistic, then we medals For the interval.
We left and right to open and close the tree line maintenance intervals, and then let each node stores the number of the current side can cover the range, and then traverse the tree line. Maintain the current view of a retractable disjoint-set, if \ (1 \) and \ (n \) in the same Ituri, then obviously it can meet the current range from \ (1 \) went \ (n \ ) , then add the contribution.

Code:

#include<map>
#include<set>
#include<queue>
#include<stack>
#include<ctime>
#include<cmath>
#include<cstdio>
#include<string>
#include<vector>
#include<cstring>
#include<sstream>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxn = 2e5 + 5;
const int INF = 0x3f3f3f3f;
const ull seed = 131;
const ll MOD = 1e9;
using namespace std;
vector<int> node[maxn << 2], vv;
int ans, n, m;
void build(int l, int r, int rt){
    node[rt].clear();
    if(l == r) return;
    int m = (l + r) >> 1;
    build(l, m, rt << 1);
    build(m + 1, r, rt << 1 | 1);
}
void update(int L, int R, int l, int r, int v, int rt){
    if(L <= l && R >= r){
        node[rt].push_back(v);
        return;
    }
    int m = (l + r) >> 1;
    if(L <= m)
        update(L, R, l, m, v, rt << 1);
    if(R > m)
        update(L, R, m + 1, r, v, rt << 1 | 1);
}
struct qu{
    int u, v, l, r;
}q[maxn];
int getid(int x){
    return lower_bound(vv.begin(), vv.end(), x) - vv.begin() + 1;
}

stack<pair<int, int> > instack;    //合并的点和其父节点暂时增加的秩
int fa[maxn], dep[maxn];
int _find(int x){
    return x == fa[x]? x : _find(fa[x]);
}
void Merge(int x, int y){
    int fx = _find(x), fy = _find(y);
    if(dep[fx] < dep[fy]){
        fa[fx] = fy;
        instack.push(make_pair(fx, 0));
    }
    else if(dep[fx] > dep[fy]){
        fa[fy] = fx;
        instack.push(make_pair(fy, 0));
    }
    else{
        fa[fx] = fy;
        dep[fy]++;
        instack.push(make_pair(fx, 1));
    }
}
void undo(){
    pair<int, int> s = instack.top();
    instack.pop();
    dep[fa[s.first]] -= s.second;
    fa[s.first] = s.first;
}
void dfs(int l, int r, int rt){
    for(int i = 0; i < node[rt].size(); i++){
        int u = q[node[rt][i]].u, v = q[node[rt][i]].v;
        Merge(u, v);
    }
    if(_find(1) == _find(n)){
        ans += vv[r] - vv[l - 1];
    }
    else if(l < r){
        int m = (l + r) >> 1;
        dfs(l, m, rt << 1);
        dfs(m + 1, r, rt << 1 | 1);
    }
    for(int i = 0; i < node[rt].size(); i++){
        undo();
    }
}
int main(){
    while(~scanf("%d%d", &n, &m)){
        for(int i = 1; i <= m; i++){
            scanf("%d%d%d%d", &q[i].u, &q[i].v, &q[i].l, &q[i].r);
            vv.push_back(q[i].l), vv.push_back(q[i].r + 1);
        }
        sort(vv.begin(), vv.end());
        vv.erase(unique(vv.begin(), vv.end()), vv.end());

        build(1, vv.size(), 1);
        for(int i = 1; i <= m; i++){
            update(getid(q[i].l), getid(q[i].r + 1) - 1, 1, vv.size(), i, 1);
        }
        for(int i = 0; i <= n; i++) fa[i] = i;
        while(!instack.empty()) instack.pop();
        ans = 0;
        dfs(1, vv.size(), 1);
        printf("%d\n", ans);
    }
    return 0;
}

Guess you like

Origin www.cnblogs.com/KirinSB/p/11391003.html