《HDU 6218》

真的波折。一开始半小时出来一个思路,写了半天的树套树,但是发现题目理解错了。

这题的桥意思是对于当前的图来说,删去这条边是否可以造成两个点不连通(也就是说图可能是不连通的)。

其实这样的情况和我一开始分析的思路也差不多。

我们以竖边来隔开各个部分,可以发现,只有在环上的边删去才不是桥。

那么我们就可以维护环上的边的条数来计算。

这里我们还要分析一些东西:

1:这个横边必须要满足上下两条都有,如果上下某条没有那么,那么它肯定无法组成环。

也就是说我们维护的横边都是上下都有的那种。

2:我们不需要一条条维护,我们直接维护整条连续的横边,因为他们被包含在同一个环中肯定有同一性质。

所以我们需要去找到这个连续横边内部的最左的竖边,和最右的竖边。那么这两条竖边和中间的横边组成的就是这段横边能组成的最大环。

有了这两点,我们就需要去维护了,首先,很明显我们可以用线段树去维护竖边(我一开始写的树套树也是这样..)

对于横边,我们可以用set去维护一整段,然后加点和拆点的时候,暴力拆除。因为我们每次操作都是单点的,所以每次的复杂度只有logn。

这里加点和删点都有几种情况,分析一下即可。

这里set有很多的问题:

因为对于多键值的情况,set对于第一关键字相等的情况也看做相同。

所以,因为左界可能存在重复次数,所以要用multiset。而且因为这里是迭代器的指针,在我们对set操作之后再去指针指向原地址,里面的数据可能已经变换了。

所以我们每次应该先计算cal再去操作set,并且我们尽量去删L,r而不是重新构建Line{L->L,L->r}这种再去删除,因为它再次去检索可能会导致删除的不是我们想要的。

// Author: levil
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int,int> pii;
#define rg register
const int N = 1e6 + 5;
const int M = 2e4 + 5;
const double eps = 1e-10;
const LL Mod = 1e9 + 7;
#define pi acos(-1)
#define INF 1e9
#define dbg(ax) cout << "now this num is " << ax << endl;
inline int read() {
    rg int f = 1,x = 0;rg char c = getchar();
    while(c < '0' || c > '9') {if(c == '-') f = -1;c = getchar();}
    while(c >= '0' && c <= '9'){x = (x<<1)+(x<<3)+(c^48);c = getchar();}
    return x*f;
}
inline long long ADD(long long x,long long y) {return (x + y) % Mod;}
inline long long DEC(long long x,long long y) {return (x - y + Mod) % Mod;}
inline long long MUL(long long x,long long y) {return x * y % Mod;}

struct Line{
    int L,r;
    bool operator < (const Line &a)const{
        return L < a.L;
    }
};
multiset<Line> S;
struct Node{int L,r,mi,mx,sum;}node[N << 2];
int sz[N],ans = 0,n;
void Pushup(int idx) {
    node[idx].mx = max(node[idx << 1].mx,node[idx << 1 | 1].mx);
    node[idx].mi = min(node[idx << 1].mi,node[idx << 1 | 1].mi);
    node[idx].sum = node[idx << 1].sum + node[idx << 1 | 1].sum;
}
void build(int L,int r,int idx) {
    node[idx].L = L,node[idx].r = r;
    if(L == r) {
        node[idx].mi = node[idx].mx = L;
        node[idx].sum = 1;
        return ;
    }
    int mid = (L + r) >> 1;
    build(L,mid,idx << 1);
    build(mid + 1,r,idx << 1 | 1);
    Pushup(idx);
}
void update(int x,int idx,int id) {
    if(node[idx].L == node[idx].r) {
        if(id == 0) node[idx].mx = -INF,node[idx].mi = INF,node[idx].sum = 0;
        else node[idx].mx = node[idx].mi = node[idx].L,node[idx].sum = 1;
        return ;
    }
    int mid = (node[idx].L + node[idx].r) >> 1;
    if(mid >= x) update(x,idx << 1,id);
    else update(x,idx << 1 | 1,id);
    Pushup(idx);
}
int query_mi(int L,int r,int idx) {
    if(node[idx].L >= L && node[idx].r <= r) return node[idx].mi;
    int mid = (node[idx].L + node[idx].r) >> 1,mi = INF;
    if(mid >= L) mi = min(mi,query_mi(L,r,idx << 1));
    if(mid < r) mi = min(mi,query_mi(L,r,idx << 1 | 1));
    return mi;
}
int query_mx(int L,int r,int idx) {
    if(node[idx].L >= L && node[idx].r <= r) return node[idx].mx;
    int mid = (node[idx].L + node[idx].r) >> 1,mx = -INF;
    if(mid >= L) mx = max(mx,query_mx(L,r,idx << 1));
    if(mid < r) mx = max(mx,query_mx(L,r,idx << 1 | 1));
    return mx;
}
int query_sum(int L,int r,int idx) {
    if(node[idx].L >= L && node[idx].r <= r) return node[idx].sum;
    int mid = (node[idx].L + node[idx].r) >> 1,sum = 0;
    if(mid >= L) sum += query_sum(L,r,idx << 1);
    if(mid < r) sum += query_sum(L,r,idx << 1 | 1);
    return sum;
}
int cal(int L,int r) {
    int le = 0,ri = 0;
    while(L < 1 || r > n) {}
    int sum = query_sum(L,r,1);
    if(sum <= 1) return 0;
    else {
        le = query_mi(L,r,1);
        ri = query_mx(L,r,1);
        return (ri - le) * 2 + sum;
    }
}
void upd_row(int x,int id) {
    if(id == 0) {
        auto L = S.upper_bound(Line{x,x + 1}); --L;
        auto r = S.lower_bound(Line{x,x + 1});
        sz[x]++;
        if(sz[x] == 1) return;
        else {
            if(L->r == x && r->L != x + 1) {
                ans -= cal(L->L,L->r);
                ans += cal(L->L,x + 1);
                S.insert(Line{L->L,x + 1});
                S.erase(L);
            }
            else if(L->r != x && r->L == x + 1) {
                ans -= cal(r->L,r->r);
                ans += cal(x,r->r);
                S.insert(Line{x,r->r});
                S.erase(r);
            }
            else if(L->r == x && r->L == x + 1) {
                ans -= cal(L->L,L->r);
                ans -= cal(r->L,r->r);
                ans += cal(L->L,r->r);
                S.insert(Line{L->L,r->r});
                S.erase(L);
                S.erase(r);
            }
            else if(L->r != x && r->L != x + 1){
                ans += cal(x,x + 1);
                S.insert(Line{x,x + 1});
            }
        }
    }
    else {
        auto p = S.upper_bound(Line{x, x + 1}); p--;
        sz[x]--;;
        if (sz[x] == 0) return;
        if (p->L == x && p->r == x + 1) {
            ans -= cal(x, x + 1);
            S.erase(p);
        }
        else if (p->L == x && p->r != x + 1)
        {
            ans += cal(x+1,p->r);
            ans -= cal(p->L,p->r);
            S.insert(Line{x+1,p->r});
            S.erase(p);
        }
        else if (p->L != x && p->r == x + 1)
        {
            ans += cal(p->L,x);
            ans -= cal(p->L,p->r);
            S.insert(Line{p->L,x});
            S.erase(p);
        }
        else if (p->L != x && p->r != x + 1)
        {
            ans -= cal(p->L, p->r);
            ans += cal(p->L, x);
            ans += cal(x+1, p->r);
            S.insert(Line{p->L, x});
            S.insert(Line{x+1, p->r});
            S.erase(p);
        }

    }
}
void upd_line(int x,int id) {
    auto L = S.upper_bound(Line{x,x});L--;
    if(id == 0) {
        if(L->r >= x) {
            ans -= cal(L->L,L->r);
            update(x,1,1);
            ans += cal(L->L,L->r);
        }
        else update(x,1,1);
    }
    else {
        if(L->r >= x) {
            ans -= cal(L->L,L->r);
            update(x,1,0);
            ans += cal(L->L,L->r);
        }
        else update(x,1,0);
    }
}
void solve() {
    int m;n = read(),m = read();
    S.clear();
    S.insert(Line{1,n});
    S.insert(Line{-1,-1});
    S.insert(Line{n + 2,n + 2});
    for(int i = 1;i <= n;++i) sz[i] = 2;
    build(1,n,1);
    int allsz = 3 * n - 2;
    ans = 3 * n - 2;
    while(m--) {
        int id,x0,y0,x1,y1;id = read(),x0 = read(),y0 = read(),x1 = read(),y1 = read();
        if(id == 1) {
            allsz++;
            if(x0 == x1) upd_row(min(y0,y1),0);
            else upd_line(min(y0,y1),0);
        }
        else {
            allsz--;
            if(x0 == x1) upd_row(min(y0,y1),1);
            else upd_line(min(y0,y1),1);
        }
        printf("%d
",allsz - ans);
    }
}
int main() {
    int ca;ca = read();
    while(ca--) {
        solve();
    }
//    system("pause");
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/zwjzwj/p/15351146.html