A-Graph Games_2019牛客暑期多校训练营(第三场)
題意
給出一張無向圖,定義S[x]表示與點(diǎn)x直接相連的點(diǎn)集,有兩個(gè)操作
1 x y表示將第x到第y條邊狀態(tài)變化(若存在則刪除,不存在則建立)
2 x y詢問S[x]與S[y]是否相等
題解
有一個(gè)技巧可以壓縮的表示點(diǎn)集:給每個(gè)點(diǎn)隨機(jī)一個(gè)key,S[x]就可以表示為
與x相連的點(diǎn)的key亦或起來。
考慮如何維護(hù)S[x], 因?yàn)樾薷牟僮魇菍?duì)輸入的順序的區(qū)間修改,我們就按邊輸入的
順序進(jìn)行分塊,用sum[i][j]記錄第i塊對(duì)點(diǎn)j的貢獻(xiàn)值,也就是如果第i塊有一條邊u-v
那么\(sum[i][u] \bigoplus= key[v], sum[i][v] \bigoplus= key[u]\)
查詢一個(gè)點(diǎn)的點(diǎn)集就變成求\(sum[1][x] \bigoplus sum[2][x] \bigoplus sum[3][x] \cdots \bigoplus sum[num][x]\)
修改的時(shí)候如果修改區(qū)間落在不同的塊上,對(duì)夾在中間的塊打個(gè)lazy標(biāo)記,表示查詢的時(shí)候
不用亦或上這個(gè)塊的貢獻(xiàn),對(duì)與兩邊塊內(nèi)的修改操作可以再用一個(gè)數(shù)組S記錄暴力修改的狀態(tài),
比如要修改區(qū)間\([l,r]\)是塊內(nèi)的,那么就修改\(S[u[i]] \bigoplus= key[v[i]], S[v[i]] \bigoplus= key[u[i]] (i\in[l,r])\)
查詢x的點(diǎn)集時(shí)再xor上S[x]就行,總的來說就是塊間修改只需要對(duì)sum打標(biāo)記,塊內(nèi)修改就
暴力更改S,最后復(fù)雜度\(O(q\sqrt m)\),分塊的時(shí)候塊數(shù)要開成\(1.5\sqrt m\)
代碼
#include <bits/stdc++.h>using namespace std; const int mx = 2e5+10; typedef long long ll;int belong[mx], block, num, l[mx], r[mx], id[mx]; int n, m, q, u[mx], v[mx]; int lazy[mx]; ll sum[450][mx], S[mx];void build() {block = 1.5*sqrt(m);num = m / block;if (m % block) num++;for (int i = 1; i <= num; i++) {l[i] = (i-1) * block + 1;r[i] = i * block;lazy[i] = 1;for (int j = 1; j <= n; j++)sum[i][j] = 0;}r[num] = m;for (int i = 1; i <= m; i++)belong[i] = (i-1) / block + 1;for (int i = 1; i <= n; i++) S[i] = 0;}void update(int x, int y) {if (belong[x] == belong[y]) {for (int i = x; i <= y; i++) {S[u[i]] ^= id[v[i]];S[v[i]] ^= id[u[i]];}return;}int L = belong[x], R = belong[y];for (register int i = x; i <= r[L]; i++) {S[u[i]] ^= id[v[i]];S[v[i]] ^= id[u[i]];}for (register int i = L+1; i < R; i++) lazy[i] ^= 1;for (register int i = l[R]; i <= y; i++) {S[u[i]] ^= id[v[i]];S[v[i]] ^= id[u[i]];} }int main() {srand(time(NULL));for (int i = 1; i < 100005; i++) id[i] = rand() + 1;int T;scanf("%d", &T);while (T--) {scanf("%d%d", &n, &m);build();for (int i = 1; i <= m; i++) {scanf("%d%d", &u[i], &v[i]);sum[belong[i]][u[i]] ^= id[v[i]];sum[belong[i]][v[i]] ^= id[u[i]];}scanf("%d", &q);while (q--) {int op, x, y;scanf("%d%d%d", &op, &x, &y);if (op == 1) {update(x, y);} else {ll ansx = S[x], ansy = S[y];for (int i = 1; i <= num; i++) {if (lazy[i]) {ansx ^= sum[i][x];ansy ^= sum[i][y];}}putchar(ansx==ansy?'1':'0');}}putchar('\n');}return 0; }轉(zhuǎn)載于:https://www.cnblogs.com/bpdwn-cnblogs/p/11290523.html
總結(jié)
以上是生活随笔為你收集整理的A-Graph Games_2019牛客暑期多校训练营(第三场)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 英语面试汇总
- 下一篇: HTML day02