ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

[噼昂!]txdy(Pending)

2021-10-07 23:00:57  阅读:201  来源: 互联网

标签:txdy int void son fa 噼昂 inline Pending define


目录

壹、关于题目 ¶

没时间去编了。

贰、关于题解 ¶

比较经典地,移动右端点指针,维护合法左端点。

左端点合法,指将 \([l,r]\) 的点都保留下来不成环且每个点度数小于等于 \(2\).

然后我们需要维护合法的左端点,一个左端点合法,当且仅当将 \([l,r]\) 的点都保留下来之后,有 \(|V_l|-|E_l|=1\).

综上,我们只需要处理三个部分:

  • 动态维护 \(d_p(p\in[l,r])\);
  • 动态维护连通性;
  • 动态维护 \(|V_l|-|E_l|\);

第一个很好维护,第二个可以考虑使用 \(\rm LCT\),第三个可以考虑线段树。

最后,合法的左端点就是线段树中 \(|V|-|E|=1\) 的部分,并且,由于 \(|V|-|E|\ge 1\),所以我们线段树实际上可以只维护最小值及其个数即可。

时间复杂度 \(\mathcal O(n\log n)\),实际跑得快不快看你的 \(\rm LCT\).

叁、参考代码 ¶

#pragma GCC optimize("Ofast")

#include <bits/stdc++.h>
using namespace std;
 
// # define USING_STDIN
// # define NDEBUG
// # define NCHECK
#include <cassert>
 
namespace Elaina {

#define rep(i, l, r) for(int i = (l), i##_end_ = (r); i <= i##_end_; ++i)
#define drep(i, l, r) for(int i = (l), i##_end_ = (r); i >= i##_end_; --i)
#define fi first
#define se second
#define mp(a, b) make_pair(a, b)
#define Endl putchar('\n')
#define whole(v) ((v).begin()), ((v).end())
#define bitcnt(s) (__builtin_popcount(s))
#ifdef NCHECK
# define iputs(Content) ((void)0)
# define iprintf(Content, argvs...) ((void)0)
#else
# define iputs(Content) fprintf(stderr, Content)
# define iprintf(Content, argvs...) fprintf(stderr, Content, argvs)
#endif
 
    typedef unsigned int uint;
    typedef long long ll;
    typedef unsigned long long ull;
    typedef pair <int, int> pii;
    typedef pair <ll, ll> pll;
    
    template <class T> inline T fab(T x) { return x < 0 ? -x : x; }
    template <class T> inline void getmin(T& x, const T rhs) { x = min(x, rhs); }
    template <class T> inline void getmax(T& x, const T rhs) { x = max(x, rhs); }
 
#ifndef USING_STDIN
    inline char freaGET() {
# define BUFFERSIZE 1 << 18
        static char BUF[BUFFERSIZE], *p1 = BUF, *p2 = BUF;
        return p1 == p2 && (p2 = (p1 = BUF) + fread(BUF, 1, BUFFERSIZE, stdin), p1 == p2) ? EOF : *p1++;
# undef BUFFERSIZE
    }
# define CHARGET freaGET()
#else
# define CHARGET getchar()
#endif
    template <class T> inline T readret(T x) {
        x=0; int f = 0; char c;
        while((c = CHARGET) < '0' || '9' < c) if(c == '-') f = 1;
        for(x = (c^48); '0' <= (c = CHARGET) && c <= '9'; x = (x << 1) + (x << 3) + (c ^ 48));
        return f ? -x : x;
    }
    template <class T> inline void readin(T& x) { x = readret(T(1)); }
    template <class T, class... Args> inline void readin(T& x, Args&... args) {
        readin(x), readin(args...);
    }

    template <class T> inline void writc(T x, char s='\n') {
        static int fwri_sta[55], fwri_ed = 0;
        if(x < 0) putchar('-'), x = -x;
        do fwri_sta[++fwri_ed] = x % 10, x /= 10; while(x);
        while(putchar(fwri_sta[fwri_ed--] ^ 48), fwri_ed);
        putchar(s);
    }

} using namespace Elaina;

const int maxn = 2.5e5;
const int inf = 0x3f3f3f3f;

int n, m;
vector <int> g[maxn + 5];
inline void add_edge(int u, int v) {
    g[u].push_back(v), g[v].push_back(u);
}

inline void input() {
    readin(n, m);
    int u, v;
    rep(i, 1, m) {
        readin(u, v);
        add_edge(u, v);
    }
}

namespace LCT {
    
    int son[maxn + 5][2], fa[maxn + 5];
    bool rev[maxn + 5];
    
    inline bool isroot(int x) {
        return son[fa[x]][0] != x && son[fa[x]][1] != x;
    }
    inline void connect(int x, int y, int d) {
        son[x][d] = y, fa[y] = x;
    }
    inline void rotate(int x) {
        int y = fa[x], z = fa[y], d = (son[y][1] == x);
        fa[x] = z; if(!isroot(y)) son[z][son[z][1] == y] = x;
        connect(y, son[x][d ^ 1], d), connect(x, y, d ^ 1);
    }
    inline void reverse(int x) {
        swap(son[x][0], son[x][1]), rev[x] ^= 1;
    }
    inline void pushdown(int x) {
        if(!rev[x]) return;
        if(son[x][0]) reverse(son[x][0]);
        if(son[x][1]) reverse(son[x][1]);
        rev[x] = 0;
    }
    inline void splay(int x) {
        static int stk[maxn + 5], ed = 0; int now = x;
        while(stk[++ed] = now, !isroot(now)) now = fa[now];
        while(ed) pushdown(stk[ed--]);
        int y, z;
        while(!isroot(x)) {
            y = fa[x], z = fa[y];
            if(!isroot(y))
                (son[z][1] == y) ^ (son[y][1] == x) ? rotate(x) : rotate(y);
            rotate(x);
        }
    }
    inline void access(int x) {
        for(int pre = 0; x; pre = x, x = fa[x])
            splay(x), son[x][1] = pre;
    }
    inline int findrt(int x) {
        access(x), splay(x), pushdown(x);
        while(son[x][0]) pushdown(x = son[x][0]);
        return splay(x), x;
    }
    inline void makert(int x) {
        access(x), splay(x), reverse(x);
    }
    inline bool link(int x, int y) {
        makert(x);
        if(findrt(y) == x) return false;
        fa[x] = y;
        return true;
    }
    inline bool cut(int x, int y) {
        makert(x);
        if(findrt(y) == x && fa[y] == x && !son[y][0]) {
            son[x][1] = fa[y] = 0;
            return true;
        }
        return false;
    }

} // using namespace saya;
int deg[maxn + 5];

namespace saya {

    int tag[maxn << 2 | 2];
    struct node {
        int mn, cnt;
        friend inline node operator + (const node& a, const node& b) {
            node ret = {min(a.mn, b.mn), 0}; 
            if(ret.mn == a.mn) ret.cnt += a.cnt;
            if(ret.mn == b.mn) ret.cnt += b.cnt;
            return ret;
        }
    } tre[maxn << 2 | 2];

#define ls (i << 1)
#define rs (i << 1 | 1)
#define mid ((l + r) >> 1)
#define _lhs ls, l, mid
#define _rhs rs, mid + 1, r

    void build(int i = 1, int l = 1, int r = n) {
        tre[i] = {0, r - l + 1}, tag[i] = 0;
        if(l == r) return;
        build(_lhs), build(_rhs);
    }
    inline void pushup(int i) { tre[i] = tre[ls] + tre[rs]; }
    inline void add(int i, int delta) { tre[i].mn += delta, tag[i] += delta; }
    inline void pushdown(int i) {
        if(!tag[i]) return;
        add(ls, tag[i]), add(rs, tag[i]), tag[i] = 0;
    }
    void modify(int ql, int qr, int delta, int i = 1, int l = 1, int r = n) {
        if(ql <= l && r <= qr) return add(i, delta);
        pushdown(i);
        if(ql <= mid) modify(ql, qr, delta, _lhs);
        if(mid < qr) modify(ql, qr, delta, _rhs);
        pushup(i);
    }
    node query(int ql, int qr, int i = 1, int l = 1, int r = n) {
        if(ql <= l && r <= qr) return tre[i];
        pushdown(i); node ret = {inf, 0};
        if(ql <= mid) ret = query(ql, qr, _lhs);
        if(mid < qr) ret = ret + query(ql, qr, _rhs);
        return ret;
    }
    void print(int i = 1, int l = 1, int r = n) {
        printf("node %d  [%d, %d] :> mn == %d, cnt == %d\n", i, l, r, tre[i].mn, tre[i].cnt);
        if(l == r) return;
        pushdown(i);
        print(_lhs), print(_rhs);
    }

#undef ls
#undef rs
#undef mid
#undef _lhs
#undef _rhs

} // using namespace saya;

inline void remove(int u, int r) {
    for(int v : g[u]) if(u <= v && v <= r) {
        if(LCT::cut(v, u)) --deg[v];
    }
}

inline void work() {
    int l = 1, r = 0;
    ll ans = 0;
    saya::build();
    while(r < n) {
        ++r; // extend the right endpos
        saya::modify(l, r, 1); // add the number of node
        for(int v : g[r]) if(l <= v && v <= r) {
            while(deg[v] == 2 || deg[r] == 2 || !LCT::link(r, v)) {
                remove(l++, r);
                if(l > v) break;
            }
            // add successfully
            if(l <= v) {
                ++deg[v], ++deg[r]; // increase the degree
                saya::modify(l, v, -1); // add the number of edge
            }
        }
        auto ret = saya::query(l, r);
        if(ret.mn == 1) ans += ret.cnt;
    }
    writc(ans);
}

signed main() {
    // freopen("txdy.in", "r", stdin);
    // freopen("txdy.out", "w", stdout);
    input();
    work();
    return 0;
}

肆、关键 の 地方 ¶

条件关于点的刻画,这是关键。另,移动右端点,维护左端点,又一次被用上。

标签:txdy,int,void,son,fa,噼昂,inline,Pending,define
来源: https://www.cnblogs.com/Arextre/p/15377503.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有