首页 > 其他分享 >[题解]AT_abc350_g [ABC350G] Mediator

[题解]AT_abc350_g [ABC350G] Mediator

时间:2024-06-23 13:12:00浏览次数:3  
标签:LCT int 题解 abc350 num ABC350G 节点 define

思路

有加边操作,一眼 LCT。问题在于处理询问操作。

首先,判断联通。如果 \(x,y\) 不在同一个联通块内,则一定没有答案。

其次,求出 \(x,y\) 之间节点的数量 \(num\)(包括 \(x,y\))。如果 \(num = 3\) 说明 \(x,y\) 之间有一个共同的节点;如果 \(num = 2\) 说明 \(x,y\) 直接连接;如果 \(num > 3\) 说明 \(x,y\) 之间有不止一个节点。

当 \(num = 3\) 时,考虑如何计算该节点的编号。维护节点的编和,查询 \(x,y\) 之间的编号和 \(sum\),答案显然就是 \(sum - x - y\)。

全都是 LCT 基本操作,难点在于会不会 LCT。

Code

#include <bits/stdc++.h>
#define fst first
#define snd second
#define re register
#define int long long

using namespace std;

typedef pair<int,int> pii;
const int N = 1e5 + 10,mod = 998244353;
int n,q,lst,f[N];

inline int read(){
    int r = 0,w = 1;
    char c = getchar();
    while (c < '0' || c > '9'){
        if (c == '-') w = -1;
        c = getchar();
    }
    while (c >= '0' && c <= '9'){
        r = (r << 3) + (r << 1) + (c ^ 48);
        c = getchar();
    }
    return r * w;
}

struct LCT{
    #define fp(u) (tr[u].fa)
    #define son(u,k) (tr[u].ch[k])
    #define getch(u) (u == son(fp(u),1))
    #define isroot(u) (u != son(fp(u),getch(u)))

    struct node{
        int fa,ch[2];
        pii val,sum;
        int tag;
    }tr[N];

    inline void calc(int u){
        if (!u) return;
        tr[u].tag ^= 1;
        swap(son(u,0),son(u,1));
    }

    inline void maintain(int u,int fa,int k,bool falg){
        if (!falg || !isroot(fp(u))) son(fa,k) = u;
        fp(u) = fa;
    }

    inline void pushup(int u){
        tr[u].sum.fst = tr[son(u,0)].sum.fst + tr[son(u,1)].sum.fst + tr[u].val.fst;
        tr[u].sum.snd = tr[son(u,0)].sum.snd + tr[son(u,1)].sum.snd + tr[u].val.snd;
    }

    inline void pushdown(int u){
        if (tr[u].tag){
            calc(son(u,0)); calc(son(u,1));
            tr[u].tag = 0;
        }
    }

    inline void update(int u){
        if (!isroot(u)) update(fp(u));
        pushdown(u);
    }

    inline void rotate(int u){
        int fa = fp(u);
        int ffa = fp(fa);
        int k = getch(u);
        maintain(son(u,k ^ 1),fa,k,false);
        maintain(u,ffa,getch(fa),true);
        maintain(fa,u,k ^ 1,false);
        pushup(fa);
    }

    inline void splay(int u){
        update(u);
        while (!isroot(u)){
            int fa = fp(u);
            if (!isroot(fa)){
                if (getch(u) != getch(fa)) rotate(u);
                else rotate(fa);
            }
            rotate(u);
        }
        pushup(u);
    }

    inline void access(int u){
        int p = 0;
        while (u){
            splay(u);
            son(u,1) = p; pushup(u);
            p = u; u = fp(u);
        }
    }

    inline void makeroot(int u){
        access(u); splay(u);
        calc(u);
    }

    inline int split(int x,int y){
        makeroot(x);
        access(y); splay(y);
        return y;
    }

    inline int find(int u){
        access(u); splay(u);
        pushdown(u);
        while (son(u,0)) pushdown(u = son(u,0));
        splay(u);
        return u;
    }

    inline void link(int x,int y){
        makeroot(x);
        if (find(y) != x) fp(x) = y;
    }

    #undef fp
    #undef son
    #undef getch
    #undef isroot
}T;

inline int find(int x){
    if (f[x] != x) return f[x] = find(f[x]);
    return f[x];
}

inline void merge(int a,int b){
    int x = find(a),y = find(b);
    if (x == y) return;
    f[x] = y;
}

signed main(){
    n = read(),q = read();
    for (re int i = 1;i <= n;i++){
        T.tr[i].val = {i,1};
        f[i] = i;
    }
    while (q--){
        int op,x,y;
        op = (read() * (1 + lst) % mod) % 2 + 1;
        x = (read() * (1 + lst) % mod) % n + 1;
        y = (read() * (1 + lst) % mod) % n + 1;
        if (op == 1){
            T.link(x,y); merge(x,y);
        }
        else{
            if (find(x) != find(y)) printf("%lld\n",lst = 0);
            else{
                pii ans = T.tr[T.split(x,y)].sum;
                if (ans.snd != 3) printf("%lld\n",lst = 0);
                else printf("%lld\n",lst = (ans.fst - x - y));
            }
        }
    }
    return 0;
}

标签:LCT,int,题解,abc350,num,ABC350G,节点,define
From: https://www.cnblogs.com/WaterSun/p/18263289

相关文章

  • [题解]AT_abc343_g [ABC343G] Compress Strings
    思路首先假设有两个串\(a,b\),如果\(b\)是\(a\)的子串,且\(a\neqb\)则不需要考虑\(b\);如果\(a=b\),则如需要保留一个\(a\)。做完上述操作后,显然最终的答案是由这些串按照一定顺序拼接起来,再删掉重叠部分。例如:abbcc与ccdde拼接为abbccccdde,发现cc是重复的,所以......
  • [题解]AT_abc342_f [ABC342F] Black Jack
    思路发现自己与庄家的操作是完全独立的,所以考虑分别计算它们。首先考虑自己的情况,定义\(dp_i\)表示掷出骰子的和为\(i\)获胜的概率,并记\(f(i)\)表示\(x=i\)时就不掷的获胜概率。对于每一步我们要么掷骰子(并且掷出的值等概率的在\(1\simD\)中),要么直接结束。两种情......
  • [题解]CF855E Salazar Slytherin's Locket
    思路毒瘤数位DP题。首先,你可以用一个vector储存每一个数字出现的次数,然后用map记忆化。然后可以得到如下TLE#8的代码。因为map自带一只\(\log\)所以,考虑将map优化掉。但是,现在每一种数字可能会出现很多次,所以要用vector维护出现次数,但这样必定需要用map一......
  • [题解]CF666B World Tour
    CSP-2022S2T1弱化版。思路首先因为边权均为\(1\),所以我们可以在\(\Theta(n^2)\)的复杂度用BFS求解出任意两点\(i,j\)的最短距离\(d_{i,j}\)(如果\(i\)不能到达\(j\),则令\(d_{i,j}=-1\))。有一个贪心的结论,就是使每一条\(A\toB,B\toC,C\toD\)的路径长度......
  • [题解]CF622F The Sum of the k-th Powers
    思路首先发现\(\sum_{i=1}^{n}i^k\)是一个\(k+1\)次多项式,那么我们需要求出\(k+2\)个点才能得到唯一的一个\(f(t)=\sum_{i=1}^{t}{i^k}\)。不难通过拉格朗日插值法,将\(x=1\sim(k+2)\)的情况一一带入:\[f(n)=\sum_{i=1}^{k+2}{((\sum_{j=1}^{i}......
  • [题解]CF622D Optimal Number Permutation
    思路首先考虑答案下界,因为\((n-i)\)和\(|d_i+i-n|\)均大于等于\(0\),所以它们相乘一定大于等于\(0\)。于是考虑能不能构造出结果为\(0\)。显然当\(i=n\)时,无论\(d_i\)的值是什么,式子的结果为\(0\)。因此只需要考虑\(i\in[1,n)\)的情况。因为要使结果为......
  • [题解]CF609F Frogs and mosquitoes
    思路发现\(x\)对题目的限制较大,因此考虑先将\(x\)排序并离散化后再来考虑。不难用线段树维护\(\max_{i=l}^{r}\{x_i+len_i\}\),这样我们就可以利用类似线段树上二分的技巧得出是哪一只青蛙吃掉的蚊子。但是有可能有一只蚊子无法吃掉,我们先把它丢进一个集合里面。每有......
  • [题解]CF988D Points and Powers of Two
    思路首先发现选出的数最多\(3\)个,考虑反证法。假设选出了四个数\(a,b,c,d\),并令:\[|a-b|=2^{x_1},|b-c|=2^{x_2},|c-d|=2^{x_3}\]又因为,\(|a-c|,|b-d|\)也都是\(2\)的次幂,那么有\(x_1=x_2=x_3\)。于是\(|a-d|=3\times2^{x_0}\neq2^k\)。在......
  • P9999 [Ynoi2000] tmostnrq 题解
    巨大难写题。就这样一个毒瘤的题,还有人把时空缩小成二分之一放在模拟赛,太好笑了。思路首先将询问离线。我们在\(l_i\)处加入这个点,在\(r_i\)处查询这个点在哪里。那么我们就需要有一个数据结构支持让所有树上的节点一起动。考虑所有点往\(x\)处动。那么对于在\(1\si......
  • LeetCode:经典题之206、92题解及延伸
    系列目录88.合并两个有序数组52.螺旋数组567.字符串的排列643.子数组最大平均数150.逆波兰表达式61.旋转链表160.相交链表83.删除排序链表中的重复元素389.找不同目录系列目录206.反转链表92.反转链表II类和结构体访问修饰符206.反转链表......