• CCPC-Wannafly Winter Camp Day3 (Div2, onsite)


    Replay


    Dup4:

    •  没想清楚就动手写? 写了两百行发现没用?想的还是不够仔细啊。
    • 要有莽一莽的精神

    X:

    • 感觉今天没啥输出啊, 就推了个公式?抄了个板子, 然后就一直自闭A。
    • 语文差,题目没理解,导致写了接近三小时的A吧, 最后看了一眼群, 发现自己理解错了。
    • 以及感觉自己最近不会交流,有点毒瘤了。 

    A:二十四点*

    Solved.

    思路:

    Div2 暴力跑?

     1 #include<bits/stdc++.h>
     2 
     3 using namespace std;
     4 
     5 int n;
     6 double arr[20];
     7 
     8 int main()
     9 {
    10     while(~scanf("%d", &n))
    11     {
    12         for(int i = 1; i <= n; ++i) scanf("%lf", arr + i);
    13         else if(n == 6) puts("32");
    14         else if(n == 10) puts("891");    
    15     
    16     }
    17     return 0;
    18 }
    View Code
     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 
     4 typedef long long ll;
     5 const ll MOD = 998244353;
     6 const double eps = 1e-8;
     7 
     8 int n, ans;
     9 double arr[12];
    10 double brr[12];
    11 
    12 int DFS(int len)
    13 {
    14     if (len == 1)
    15     {
    16         if (fabs(brr[1] - 24.0) < eps) return 1;
    17         else return 0;
    18     }
    19 
    20     for (int i = 1; i <= len; ++i)
    21     {
    22         for (int j = i + 1; j <= len; ++j)
    23         {
    24             double a = brr[i], b = brr[j], c = brr[len];
    25             brr[j] = c;
    26             double tmp = a + b;
    27             brr[i] = tmp;
    28             if (fabs(tmp - 24.0) < eps) return 1;
    29             if (DFS(len - 1)) return 1;
    30 
    31             tmp = a - b;
    32             brr[i] = tmp;
    33             if (fabs(tmp - 24.0) < eps) return 1;
    34             if (DFS(len - 1)) return 1;
    35 
    36             tmp = b - a;
    37             brr[i] = tmp;
    38             if (fabs(tmp - 24.0) < eps) return 1;
    39             if (DFS(len - 1)) return 1;
    40 
    41             tmp = a * b;
    42             brr[i] = tmp;
    43             if (fabs(tmp - 24.0) < eps) return 1;
    44             if (DFS(len - 1)) return 1;
    45 
    46             tmp = a / b;
    47             brr[i] = tmp;
    48             if (fabs(tmp - 24.0) < eps) return 1;
    49             if (DFS(len - 1)) return 1;
    50 
    51             tmp = b / a;
    52             brr[i] = tmp;
    53             if (fabs(tmp - 24.0) < eps) return 1;
    54             if (DFS(len - 1)) return 1;
    55 
    56 
    57             brr[i] = a, brr[j] = b, brr[len] = c;
    58         }
    59     }
    60 
    61     return 0;
    62 }
    63 
    64 void RUN()
    65 {
    66     while (~scanf("%d", &n))
    67     {
    68         for (int i = 1; i <= n; ++i) scanf("%lf", arr + i);
    69         ans = 0;
    70         for (int i = 0; i < (1 << n); ++i)
    71         {
    72             int tot = 0;
    73             for (int j = 0; j < n; ++j)
    74             {
    75                 if (i & (1 << j))
    76                 {
    77                     brr[++tot] = arr[j + 1];
    78                 }
    79             }
    80             int tmp = DFS(tot);
    81             ans += tmp;
    82         }
    83         printf("%d
    ", ans);
    84     }
    85 }
    86 
    87 int main()
    88 {
    89     RUN();
    90     return 0;
    91 }
    View Code

    D:精简改良

    Upsolved.

    生成树状压DP

    $dp[S][u] 表示点集为S, 根节点为u的最大贡献$

    $dp[S][u] = max(dp[T][v] + dp[S - T][u] + dist[u][v] cdot |T| cdot |n - T|)$

    $T表示点集为T 并且根节点为v的子树,并且T是S的子集$

    $要注意有些非法的状态是不能够参与转移的$

    $时间复杂度O(3^n cdot n^2)$

    $对于每一个集合枚举其子集  相当于 sumlimits_{0}^{n} C_n^i cdot 2^i = (1 + 2)^n = 3^n$

    但是这里过不去 要卡点常 喵喵喵?  预处理了一下子集中有哪些点

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 
     4 #define ll long long
     5 #define INFLL 0x3f3f3f3f3f3f3f3f
     6 #define N 110
     7 int n, m;
     8 int dist[20][20];
     9 ll f[1 << 15][15];
    10 
    11 vector <int> vec[1 << 15];
    12 int sze[1 << 15];
    13 
    14 int main()
    15 {
    16     while (scanf("%d%d", &n, &m) != EOF)
    17     {
    18         memset(dist, -1, sizeof dist); 
    19         memset(f, -1, sizeof f);
    20         for (int S = 0, len = (1 << n); S < len; ++S) 
    21         {
    22             for (int i = 0; i < n; ++i) if ((S >> i) & 1)
    23                 vec[S].push_back(i + 1); 
    24             sze[S] = vec[S].size();
    25             if (sze[S] == 1)
    26                 f[S][*vec[S].begin()] = 0; 
    27         }    
    28         for (int i = 1, u, v, w; i <= m; ++i)
    29         {
    30             scanf("%d%d%d", &u, &v, &w);
    31             dist[u][v] = dist[v][u] = w; 
    32         }
    33         ll res = 0;  
    34         for (int S = 1, len = (1 << n); S < len; ++S)
    35         {  
    36             for (auto u : vec[S])
    37             {
    38                 for (int T = (S - 1) & S; T != 0; T = (T - 1) & S) // 枚举子集  
    39                 {
    40                     for (auto v : vec[T])
    41                     {
    42                         if (dist[u][v] == -1 || f[T][v] == -1 || f[S - T][u] == -1) continue;   
    43                         f[S][u] = max(f[S][u], f[T][v] + f[S - T][u] + 1ll * dist[u][v] * sze[T] * (n - sze[T]));  
    44                     }
    45                 }
    46                 if (S == (1 << n) - 1)res = max(res, f[S][u]);
    47             }
    48         }
    49         printf("%lld
    ", res);
    50     }
    51     return 0;
    52 }
    View Code

    E:最大独立集

    Upsolved.

    树上独立集的贪心做法:

    每次取出叶子节点加入答案,然后将其父节点扔掉,循环操作,直至没有节点

    那么考虑这一道题的操作,对于一棵树$T(k_i)来说$

    它的每一个节点下面都连着一棵独立的树

    那么这些独立的树都可以分别贪心求最大独立集

    再考虑这些独立的树做完之后剩下的$T(k_i)$

    如果这些独立的树的最大独立集需要取到其根节点,那么$T(k_i)中所有节点都不能取$

    否则$T(k_i)的贡献就是以k_i为根的最大独立集$

    这时候需要预处理出以$x in [1, n] 为根的最大独立集中是否需要用到x$

    树形dp

    第一次dp ,$f[i] 表示只考虑i的子树当前点 取不取$

    显然,对于所有叶子节点都是取的 ,$f[i] = 1$

    那么对于非叶子节点 $f[i] = 1 当且仅当其所有儿子的f[i] = 0$

    第二次dp $g[i] 表示不考虑i的子树当前点取不取$

    显然,$g[1] = 1 表示根节点不考虑其子树是取的$

    再考虑其他点$u,如果u是不取的,当且仅当 g[fa[u]] = 1 并且 其父亲除它$

    $以外的儿子中的f[i]都是不取的$

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 
     4 #define ll long long
     5 #define N 200010
     6 const ll MOD = (ll)998244353;
     7 int n, m; ll base; 
     8 vector <int> G[N]; 
     9 
    10 int fa[N], cnt[N], need[N];
    11 // 0 get > 0 not get  for cnt
    12 void DFS(int u)
    13 {
    14     cnt[u] = 0;
    15     for (auto v : G[u]) if (v != fa[u])
    16     {
    17         fa[v] = u;
    18         DFS(v); 
    19         if (cnt[v] == 0) ++cnt[u];  
    20     }
    21     if (cnt[u] == 0) ++base;
    22 }
    23 
    24 
    25 // need 0 get 1 not get 
    26 void DFS2(int u)
    27 {
    28     if (u != 1)
    29     {
    30         if (need[fa[u]] == 0 && cnt[fa[u]] - (cnt[u] == 0) == 0) need[u] = 1;
    31         else need[u] = 0;
    32     }
    33     for (auto v : G[u]) if (v != fa[u])
    34         DFS2(v); 
    35 }
    36 
    37 int main()
    38 {
    39     while (scanf("%d%d", &n, &m) != EOF)
    40     {
    41         base = 0;
    42         for (int i = 1; i <= n; ++i) G[i].clear();
    43         for (int i = 1, u, v; i < n; ++i)
    44         {
    45             scanf("%d%d", &u, &v);
    46             G[u].push_back(v);
    47             G[v].push_back(u);
    48         }
    49         DFS(1); 
    50         need[1] = 0;
    51         DFS2(1);
    52         for (int i = 1; i <= n; ++i) 
    53         {
    54             if (cnt[i] == 0 && need[i] == 0) need[i] = 1;
    55             else need[i] = 0;
    56         }
    57         ll res = base;        
    58         int vis = need[1];  
    59         for (int i = 1, x; i <= m; ++i)
    60         {
    61             scanf("%d", &x);
    62             printf("%lld
    ", res);
    63             res = (res * n) % MOD; 
    64             if (vis == 0) res = (res + base) % MOD, vis = need[x]; 
    65             else vis = 0;  
    66         }        
    67         printf("%lld
    ", res);
    68     }
    69     return 0;
    70 }
    View Code

    F:小清新数论*

    Solved.

    思路:

    $ans = sumlimits_{d = 1}^n cdot mu(d) sumlimits_{i = 1}^{frac{n}{d}} sumlimits_{j = 1}^{frac{n}{d}} [gcd(i, j) == 1]$

     1 #include<bits/stdc++.h>
     2 
     3 using namespace std;
     4 
     5 typedef long long ll;
     6 
     7 const ll MOD = 998244353;
     8 const int maxn = 1e7 + 10;
     9 
    10 bool check[maxn];
    11 int prime[maxn];
    12 int mu[maxn];
    13 ll sum[maxn];
    14 
    15 void Moblus()
    16 {
    17     mu[1] = 1;
    18     int tot = 0;
    19     for(int i = 2; i < maxn; ++i)
    20     {
    21         if(!check[i])
    22         {
    23             prime[tot++] = i;
    24             mu[i] = -1;
    25         }
    26         for(int j = 0; j < tot; ++j)
    27         {
    28             if(i * prime[j] > maxn) break;
    29             check[i * prime[j]] = true;
    30                if(i % prime[j] == 0)
    31             {
    32                 mu[i * prime[j]] = 0;
    33                 break;
    34             }    
    35             else
    36             {
    37                 mu[i * prime[j]] = -mu[i];
    38             }
    39         }
    40     }
    41     for(int i = 1; i < maxn; ++i)
    42     {
    43         sum[i] = (sum[i - 1] + mu[i]) % MOD;
    44     }
    45 }
    46 
    47 ll solve(int n, int m)
    48 {
    49     ll ans = 0;
    50     if(n > m) swap(n, m);
    51     for(int i = 1, la = 0; i <= n; i = la + 1)
    52     {
    53         la = min(n / (n / i), m / (m / i));
    54         ans += (sum[la] - sum[i - 1]) * (n / i) * (n / i);
    55     }
    56     return ans;
    57 }
    58 
    59 int n;
    60 
    61 int main()
    62 {
    63     Moblus();
    64     while(~scanf("%d", &n))
    65     {
    66         ll ans = 0;
    67         for(int i = 1; i <= n; ++i)
    68         {
    69             ans = (ans + mu[i] * solve(n / i, n / i) % MOD + MOD) % MOD;
    70         }
    71         printf("%lld
    ", ans);
    72     }
    73     return 0;
    74 }
    View Code

    G:排列

    Solved.

    签到。

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 
     4 #define N 100010
     5 int n, q[N], p[N], vis[N];
     6 
     7 int main()
     8 {
     9     while (scanf("%d", &n) != EOF)
    10     {
    11         memset(vis, 0, sizeof vis);
    12         memset(p, 0, sizeof p);
    13         for (int i = 1; i <= n; ++i) scanf("%d", q + i);
    14         int j = 1;
    15         for (int i = 1; i <= n; ++i)
    16         {
    17             if (i == 1 || q[i] < q[i - 1])
    18             {
    19                 vis[j] = 1;
    20                 p[q[i]] = j;
    21                 ++j;
    22             }
    23         }
    24         for (int i = 1; i <= n; ++i) if (!p[i]) 
    25             p[i] = j++;
    26         for (int i = 1; i <= n; ++i) printf("%d%c", p[i], " 
    "[i == n]);
    27     }
    28     return 0;
    29 }
    View Code

    H:涂鸦*

    Solved.

    思路:

    对于某一个点来说,它被染成黑点的概率是$frac{(x - l + 1) cdot (r - x + 1) cdot 2}{(r - l + 1) cdot (r - l + 2)}$ 

    然后二维BIT维护矩形,最后将所有未被矩形覆盖的期望加起来即可

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 
     4 #define ll long long
     5 #define N 1010
     6 const ll p = (ll)998244353;
     7 const ll MOD = (ll)998244353;
     8 int n, m, q;
     9 ll inv[N];
    10 int ans[N][N];
    11 
    12 namespace BIT
    13 {
    14     int a[N][N];
    15     void init() { memset(a, 0, sizeof a); }
    16     void update(int x, int y, int v)
    17     {
    18         for (int i = x; i > 0; i -= i & -i)
    19             for (int j = y; j > 0; j -= j & -j)
    20                 a[i][j] += v;
    21     }
    22     int query(int x, int y)
    23     {
    24         int res = 0;
    25         for (int i = x; i < N; i += i & -i)
    26             for (int j = y; j < N; j += j & -j)
    27                 res += a[i][j];
    28         return res;
    29     }
    30     void update(int x1, int y1, int x2, int y2)
    31     {
    32         update(x1 - 1, y1 - 1, 1);
    33         update(x1 - 1, y2, -1);
    34         update(x2, y1 - 1, -1);
    35         update(x2, y2, 1);
    36     }
    37 }
    38 
    39 int main()
    40 {
    41     inv[1] = 1;
    42     for (int i = 2; i < N; ++i) inv[i] = inv[p % i] * (p - p / i) % p; 
    43     while (scanf("%d%d%d", &n, &m, &q) != EOF)
    44     {
    45         memset(ans, 0, sizeof ans); BIT::init(); 
    46         for (int i = 1, l, r; i <= n; ++i)
    47         {
    48             scanf("%d%d", &l, &r);
    49             for (int j = l; j <= r; ++j) 
    50                 ans[i][j] = 2ll * (j - l + 1) %p * (r - j + 1) %p * inv[r - l + 1] % p * inv[r - l + 2] % p; 
    51             //cout << ans[i][l] * (r - l + 1) * (r - l + 2) / 2 % p << endl;
    52         }
    53         for (int qq = 1; qq <= q; ++qq)
    54         {
    55             int x1, x2, y1, y2;
    56             scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
    57             BIT::update(x1, y1, x2, y2);
    58         }    
    59         ll res = 0;
    60         for (int i = 1; i <= n; ++i) for (int j = 1; j <= m; ++j) if (!BIT::query(i, j))
    61         {
    62             //cout << i << " " << j << endl;
    63             res = (res + ans[i][j]) % p;
    64         }
    65         printf("%lld
    ", res);
    66     }
    67     return 0;
    68 }
    View Code

    I:石头剪刀布

    Solved.

    思路:

    考虑有$x之前要被a个人挑战,要挑战b个人$

    那么$此时对于x满足的方案数是3^n cdot frac{1}{3}^b cdot frac{2}{3}^a$

    然后考虑怎么维护$a和b$

    我们发现对于1操作

    我们将$y 接在 x 下面的话,这样最后会构成一棵树$

    那么$b就是祖宗的个数$

    再考虑$a是什么,我们发现其实就是 它的所有祖先当中 所有比它后加入的儿子个数 以及它所有的儿子个数$

    然后再发现一棵子树对其他点的影响,发现受影响的点就是它的父亲中比它先来的儿子中所对应的所有子树

    这一段在$DFS序中是连续的,线段树维护即可$

    刚开始错误思路,写了个树剖,喵喵喵?

      1 #include <bits/stdc++.h>
      2 using namespace std;
      3 
      4 #define ll long long
      5 #define N 200010
      6 const ll MOD = (ll)998244353;
      7 int n, m, fa[N];
      8 vector <int> G[N];
      9 struct qnode
     10 {
     11     int op, x, y;
     12     void scan()
     13     {
     14         scanf("%d%d", &op, &x); ++x;
     15         if (op == 1) 
     16         {
     17             scanf("%d", &y); ++y;
     18             fa[y] = x;
     19             G[x].push_back(y); 
     20         }
     21     }
     22 }q[N];
     23 
     24 int deep[N], sze[N], top[N], son[N], lp[N], rp[N], fp[N], cnt; 
     25 void DFS(int u)
     26 {
     27     sze[u] = 1;
     28     for (auto v : G[u]) if (v != fa[u])
     29     {
     30         deep[v] = deep[u] + 1;
     31         DFS(v);
     32         sze[u] += sze[v];
     33         if (!son[u] && sze[v] > sze[son[u]]) son[u] = v; 
     34     }
     35 }
     36 
     37 void getpos(int u, int sp)
     38 {
     39     top[u] = sp;
     40     lp[u] = ++cnt;
     41     fp[cnt] = u;
     42     if (!son[u])
     43     {
     44         rp[u] = cnt;
     45         return;
     46     }
     47     getpos(son[u], sp);
     48     for (auto v : G[u]) if (v != fa[u] && v != son[u])
     49         getpos(v, v);
     50     rp[u] = cnt;
     51 }
     52 
     53 namespace SEG
     54 {
     55     struct node
     56     {
     57         int v[2], lazy[2];
     58         node() {}
     59         void init()
     60         {
     61             memset(v, 0, sizeof v);
     62             memset(lazy, 0, sizeof lazy);
     63         }
     64         node operator + (const node &other) const
     65         {
     66             node res; res.init();
     67             for (int i = 0; i < 2; ++i) res.v[i] = v[i] + other.v[i];
     68             return res;
     69         }
     70     }a[N << 2], res;
     71     void build(int id, int l, int r)
     72     {
     73         a[id].init();
     74         if (l == r)
     75         {
     76             a[id].v[0] = deep[fp[l]];
     77             return;
     78         }
     79         int mid = (l + r) >> 1;
     80         build(id << 1, l, mid);
     81         build(id << 1 | 1, mid + 1, r);
     82     }
     83     void pushdown(int id)
     84     {
     85         for (int i = 0; i < 2; ++i) if (a[id].lazy[i])
     86         {
     87             int lazy = a[id].lazy[i];
     88             a[id].lazy[i] = 0;
     89             a[id << 1].v[i] += lazy;
     90             a[id << 1 | 1].v[i] += lazy;
     91             a[id << 1].lazy[i] += lazy;
     92             a[id << 1 | 1].lazy[i] += lazy;
     93         }
     94     }
     95     void update(int id, int l, int r, int ql, int qr, int v, int vis) 
     96     {
     97         if (l >= ql && r <= qr)
     98         {
     99             a[id].v[vis] += v;
    100             a[id].lazy[vis] += v;
    101             return;
    102         }
    103         int mid = (l + r) >> 1;
    104         pushdown(id);
    105         if (ql <= mid) update(id << 1, l, mid, ql, qr, v, vis);
    106         if (qr > mid) update(id << 1 | 1, mid + 1, r, ql, qr, v, vis);
    107     }
    108     void query(int id, int l, int r, int pos)
    109     {
    110         if (l == r) 
    111         {
    112             res = a[id];
    113             return;
    114         }
    115         int mid = (l + r) >> 1;
    116         pushdown(id);
    117         if (pos <= mid) query(id << 1, l, mid, pos);
    118         else query(id << 1 | 1, mid + 1,r , pos);
    119     }
    120 }
    121 
    122 ll qmod(ll base, ll n)
    123 {
    124     ll res = 1;
    125     while (n)
    126     {
    127         if (n & 1) res = (res * base) % MOD;
    128         base = base * base % MOD;
    129         n >>= 1;
    130     }
    131     return res;
    132 }
    133 ll ans[N];
    134 
    135 int main()
    136 {    
    137     while (scanf("%d%d", &n, &m) != EOF)
    138     {
    139         ++n;
    140         for (int i = 1; i <= n; ++i) G[i].clear();
    141         memset(fa, 0, sizeof fa);
    142         memset(son, 0, sizeof son); cnt = 0;
    143         for (int i = 1; i <= m; ++i) q[i].scan();
    144         for (int i = 2; i <= n; ++i) if (!fa[i]) 
    145         {
    146             fa[i] = 1;
    147             G[1].push_back(i); 
    148         }
    149         deep[1] = -1;
    150         DFS(1); getpos(1, 1);
    151         SEG::build(1, 1, n);
    152         for (int i = 2; i <= n; ++i) if (fa[i] != 1)
    153             SEG::update(1, 1, n, lp[fa[i]], lp[i] - 1, 1, 1);  
    154         for (int i = m; i >= 1; --i)
    155         {
    156             if (q[i].op == 2)
    157             {
    158                 SEG::res.init();
    159                 SEG::query(1, 1, n, lp[q[i].x]);
    160                 int x = SEG::res.v[0], y = SEG::res.v[1];
    161                 ans[i] = qmod(3, n - x - y - 1) * qmod(2, y) % MOD;
    162             }
    163             else
    164             {    
    165                 SEG::res.init(); 
    166                 SEG::query(1, 1, n, lp[q[i].y]); 
    167                 int x = SEG::res.v[0];
    168                 SEG::update(1, 1, n, lp[q[i].y], rp[q[i].y], -x, 0);
    169                 SEG::update(1, 1, n, lp[q[i].x], lp[q[i].y] - 1, -1, 1);
    170             }
    171         }
    172         for (int i = 1; i <= m; ++i) if (q[i].op == 2) printf("%lld
    ", ans[i]);
    173     }
    174     return 0;
    175 }
    View Code

     并查集

    按秩合并(为什么路径压缩不可以呢, 据说是因为破坏了树结构?)

    每次对于$x$, $y$两个集合

    当把$y$集合合并到$x$集合中时:

    • 使得$y$上的总比赛场次增量减去$x$原本的总比赛场次增量, 同时使得$x$总比赛场次增量增加
    • 使得$x$总主场场次增量增加, 同时使得$y$上的总主场场次增量减去$x$现在的总主场场次增量

    当把$x$集合合并到$y$集合中时:

    • 使得$x$上的总比赛场次增量减去$y$原本的总比赛场次增量, 同时使得$y$总比赛场次增量增加
    • 使得$x$上的总主场场次增量减去$y$原本的总主场场次增量, 同时是的$x$总主场场次增量增加

    在寻找根节点时, 统计路径上的总主场场次增量$a$以及总主场场次增量$b$

    那么此时方案数为$3^ncdot2^acdot(frac{1}{3})^b$

      1 #include<bits/stdc++.h>
      2 
      3 using namespace std;
      4 
      5 typedef long long ll;
      6 
      7 const ll MOD = 998244353;
      8 const int maxn = 2e5 + 10;
      9 
     10 ll qpow(ll x, ll n)
     11 {
     12     assert(n >= 0);
     13     ll res = 1;
     14     while (n)
     15     {
     16         if (n & 1) res = res * x % MOD;
     17         x = x * x % MOD;
     18         n >>= 1;
     19     }
     20     return res;
     21 }
     22 
     23 struct node {
     24     int father;
     25     int dw;
     26     int dv;
     27     node() {}
     28     node(int father, int dw, int dv) :father(father), dw(dw), dv(dv) {}
     29 };
     30 
     31 int n, m;
     32 int fa[maxn];
     33 int rk[maxn];
     34 int w[maxn], v[maxn];//sum 主
     35 int dw[maxn], dv[maxn];
     36 int tot;
     37 
     38 void Init()
     39 {
     40     tot = n + 1;
     41     for (int i = 1; i < maxn; ++i) fa[i] = i, w[i] = 0, v[i] = 0, rk[i] = 0;
     42 }
     43 
     44 node find(int x)
     45 {
     46     if (x == fa[x]) return node(fa[x], dw[x], dv[x]);
     47     node temp = find(fa[x]);
     48     return node(temp.father, temp.dw + dw[x], temp.dv + dv[x]);
     49 }
     50 
     51 void Mix(int x, int y)
     52 {
     53     x = find(x).father, y = find(y).father;
     54     if (rk[x] >= rk[y])
     55     {
     56         rk[x] = max(rk[x], rk[y] + 1);
     57         fa[y] = x;
     58         
     59         dw[y] -= dw[x];
     60         dw[x]++;
     61         dv[x]++;
     62         dv[y] -= dv[x];
     63     }
     64     else
     65     {
     66         rk[y] = max(rk[y], rk[x] + 1);
     67         fa[x] = y;
     68 
     69         dw[x] -= dw[y];
     70         dw[y]++;
     71         dv[x]++;
     72         dv[x] -= dv[y];
     73     }
     74 }
     75 
     76 void RUN()
     77 {
     78     while (~scanf("%d %d", &n, &m))
     79     {
     80         Init();
     81         for (int q = 1, op, x, y; q <= m; ++q)
     82         {
     83             scanf("%d", &op);
     84             if (op == 1)
     85             {
     86                 scanf("%d %d", &x, &y);
     87                 Mix(x, y);
     88             }
     89             else if (op == 2)
     90             {
     91                 scanf("%d", &x);
     92                 node tmp = find(x);
     93                 ll ans = qpow(3, n) * qpow((qpow(3, tmp.dw)), MOD - 2) % MOD * qpow(2, tmp.dv) % MOD;
     94                 printf("%lld
    ", ans);
     95             }
     96         }
     97     }
     98 }
     99 
    100 int main()
    101 {
    102 #ifdef LOCAL_JUDGE
    103     freopen("Text.txt", "r", stdin);
    104 #endif // LOCAL_JUDGE
    105 
    106     RUN();
    107 
    108 #ifdef LOCAL_JUDGE
    109     fclose(stdin);
    110 #endif // LOCAL_JUDGEf
    111 
    112     return 0;
    113 }
    View Code
  • 相关阅读:
    makefile简单例子
    js归并排序
    js插入排序
    js堆排序
    js选择排序
    js冒泡算法以及优化
    使用go语言判断不同数据类型
    go使用接口案例排序
    go接口使用案例晓demo
    go面向对象-继承
  • 原文地址:https://www.cnblogs.com/Dup4/p/10305427.html