2017年10月6日提高组T2 有趣的异或

来源:互联网 发布:js为标签添加属性 编辑:程序博客网 时间:2024/06/05 16:21

Description


这里写图片描述

Input


这里写图片描述

Output


这里写图片描述

Hint


这里写图片描述

Solution


看到判断真假条件的都要想到并查集了(哭
但是这里我并没有用并查集做法

考虑我们如果已经得到了目标序列a,并记录一个前缀异或数组s,则对于全部的询问l, r, k都要满足s[r]xor s[l-1]=k。那么我们对于一个操作l, r, k,若l-1和r同属于一个集合就判断他们之间的路径是否为k,若他们不属于同一个集合就连权为k的边合并

这里在合并的时候有一个技巧就是小的并上大的,这样每次dfs小集合更改异或值的时候就总的复杂度就是NlogN了

对于每一个独立的集合,只要任意一个数字确定了剩下的数字就都确定了。那么每个集合内第一个遇到的数字填0就可以了。注意一下这里的0是序列a的值,并不是前缀异或和s

Code


#include <stdio.h>#include <string.h>#include <math.h>#include <iostream>#include <algorithm>#define rep(i, st, ed) for (int i = st; i <= ed; i += 1)#define drp(i, st, ed) for (int i = st; i >= ed; i -= 1)#define erg(i, st) for (int i = ls[st]; i; i = e[i].next)#define fill(x, t) memset(x, t, sizeof(x))#define max(x, y) ((x)>(y)?(x):(y))#define min(x, y) ((x)<(y)?(x):(y))#define abs(x) ((x)<(0)?(-(x)):(x))#define N 400001#define E N << 2 | 1#define L 11struct edge {int x, y, w, next;} e[E];int used[N], size[N], dis[N], fa[N], ls[N], edgeCnt = 0;inline int read() {    int x = 0; char ch = getchar();    for(; ch<'0'||ch>'9'; ch=getchar());    for(; ch<='9'&&ch>='0'; (x*=10)+=ch-'0',ch=getchar());    return x;}inline void writeln(int x){    char ch[L] = {}; int i = 0;    do {ch[++ i] = '0' + x % 10;} while (x /= 10);    while (i) putchar(ch[i --]);    putchar('\n');}inline void addEdge(int x, int y, int w) {    e[++ edgeCnt] = (edge) {x, y, w, ls[x]}; ls[x] = edgeCnt;    e[++ edgeCnt] = (edge) {y, x, w, ls[y]}; ls[y] = edgeCnt;}inline void swap(int &x, int &y) {    x ^= y;    y ^= x;    x ^= y;}inline int getFather(int now) {    return ((now == fa[now])?(now):(fa[now] = getFather(fa[now])));}inline int getDis(int x, int y) {    return dis[x] ^ dis[y];}inline void dfs(int f, int now) {    used[now] = 1;    erg(i, now) {        if (e[i].y == f) {            continue;        }        dis[e[i].y] = dis[now] ^ e[i].w;        dfs(now, e[i].y);    }}int main(void) {    int n = read() + 1;    int m = read();    int czy = read();    int lastAns = 0;    rep(i, 1, n) {        fa[i] = i;        size[i] = 1;    }    while (m --) {        int l = read() ^ (czy * lastAns);        int r = read() ^ (czy * lastAns);        int k = read() ^ (czy * lastAns);        r += 1;        int fl = getFather(l);        int fr = getFather(r);        if (fl == fr) {            lastAns = (k == getDis(l, r));        } else {            addEdge(l, r, k);            if (size[fl] < size[fr]) {                swap(l, r);                swap(fl, fr);            }            size[fl] += size[fr];            dis[r] = dis[l] ^ k;            dfs(l, r);            fa[fr] = fl;            lastAns = 1;        }        writeln(lastAns);    }    fill(used, 0);    rep(i, 1, n) {        if (!used[i]) {            dis[i] = dis[i - 1];            dfs(0, i);        }    }    rep(i, 2, n) {        int prt = getDis(i, i - 1);        writeln(prt);    }    return 0;}
原创粉丝点击