It’s universally acknowledged that there’re innumerable trees in the campus of HUST.
One day the tree manager wants to play a game with you. There are N trees lining up in a straight road. The beauty of a set of trees is defined as the bitwise XOR sum of the heights of these trees. The game will last for M rounds, and each time he will tell you an interval [L i,R i] and its beauty. However, he mixed some fake messages with the correct ones. Your task is to find the messages that cannot logically correspond to its former correct messages. Otherwise you’ll think the message is correct.
One day the tree manager wants to play a game with you. There are N trees lining up in a straight road. The beauty of a set of trees is defined as the bitwise XOR sum of the heights of these trees. The game will last for M rounds, and each time he will tell you an interval [L i,R i] and its beauty. However, he mixed some fake messages with the correct ones. Your task is to find the messages that cannot logically correspond to its former correct messages. Otherwise you’ll think the message is correct.
输入描述:
The first line contains two integer N and M(1≤N,M≤105), the number of trees and the rounds of game. Then M lines followed, in each line are three integer L, R and k(1≤L≤R≤N,0≤k≤109), indicating that the beauty of [Li,Ri] is k.
输出描述:
If the i-th message is wrong, then print i in a single line. If there is no mistake, print -1.
题意:有n个数,每次给你一个信息l, r, k,代表a[l] ^ a[l+1] ^ ... ^ a[r] = k,问你哪些信息是错误的,如果x信息和y信息可以x对y错或者x错y对,那么认为先给出的信息是对的。
思路:(学长提供)
并查集路径压缩。 记a数组的前缀异或和是sum,那么信息l, r, k实际上就是sum[r] ^ sum[l-1] = k,如果已知sum[r] ^ sum[x] = k1, sum[l-1] ^ sum[x] = k2,那么只要判断k1 ^ k2是否等于k即可,否则设sum[r] ^ sum[x] = k1, sum[l-1] ^ sum[y] = k2,那么有sum[x] ^ sum[y] = k1 ^ k2 ^ k,可以将合并x,y,并设sum[x]^sum[y] = k1^k2^k, 然后直接用路径压缩就好了。
与HDU 3088类似 https://blog.youkuaiyun.com/deepseazbw/article/details/79324733
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e5+10;
int parent[N];
int sum[N]; //记录当前结点到根结点的距离
int root(int x)
{
if(parent[x]==x) return x;//一直到寻找到根节点
int t=parent[x]; //存贮中间节点
parent[x]=root(parent[x]);
sum[x]^=sum[t];
return parent[x];
}
void merge(int x,int y,int a,int b,int v)
{
parent[x]=y;
sum[x]=sum[b]^sum[a]^v;
}
int main()
{
int n,m;
while(scanf("%d%d",&n,&m)!=EOF)
{
vector<int> vec;
for(int i=0; i<=n; i++)
parent[i]=i;
memset(sum,0,sizeof(sum));
int a,b,v;
for(int pos=1; pos<=m; pos++)
{
scanf("%d%d%d",&a,&b,&v);
a--;
int x=root(a);
int y=root(b);
if(x==y) //同根节点,但值不为之前的事实
{
if((sum[a]^sum[b])!=v)
vec.push_back(pos);
}
else
{
merge(x,y,a,b,v);
}
}
if(!vec.size())
vec.push_back(-1);
for(int i=0; i<vec.size(); i++)
printf("%d\n",vec[i]);
}
}