题型很普通,
写起来有一些细节要注意,
于是记录一下。
题目链接:http://poj.org/problem?id=2827
题意:
给定一个序列,
给出一些形如(i,j,sum)的询问,
代表元素i到元素j之间的闭区间元素的和为sum。
若此询问与之前的正确询问矛盾,
则此询问错误,输出正确值。
否则此询问正确。
算法:
对于属于同一集合的元素,
根节点是该集合中最小的元素。
d[x]维护的是(p[x],x]区间的元素和。
合并时需注意要保持根节点始终是最小值
trick:i可能大于j
代码如下:
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<sstream>
#include<cstdlib>
#include<cstring>
#include<string>
#include<climits>
#include<cmath>
#include<queue>
#include<vector>
#include<stack>
#include<set>
#include<map>
#define INF 0x3f3f3f3f
#define eps 1e-8
using namespace std;
const int MAXN=110000;
int a[MAXN],b[MAXN],p[MAXN];
long long c[MAXN],d[MAXN];
vector<int> hash;
long long findp(int x) {
if(p[x]==-1) {
return x;
}
int ret=findp(p[x]);
d[x]+=d[p[x]];
return p[x]=ret;
}
int main() {
int m;
while(scanf("%d",&m)==1) {
hash.clear();
memset(p,-1,sizeof(p));
memset(d,0,sizeof(d));
for(int i=0; i<m; i++) {
scanf("%d%d%lld",&a[i],&b[i],&c[i]);
if(a[i]>b[i]) {
swap(a[i],b[i]);
}
hash.push_back(a[i]-1);
hash.push_back(b[i]);
}
sort(hash.begin(),hash.end());
hash.erase(unique(hash.begin(),hash.end()),hash.end());
for(int i=0; i<m; i++) {
a[i]=lower_bound(hash.begin(),hash.end(),a[i]-1)-hash.begin();
b[i]=lower_bound(hash.begin(),hash.end(),b[i])-hash.begin();
int px=findp(a[i]);
int py=findp(b[i]);
if(px==py) {
if(d[b[i]]-d[a[i]]==c[i]) {
puts("Accept");
} else {
printf("Bug Detected %lld\n",d[b[i]]-d[a[i]]);
}
} else {
if(px>py) {
swap(a[i],b[i]);
swap(px,py);
c[i]=-c[i];
}
d[py]=d[a[i]]+c[i]-d[b[i]];
p[py]=px;
puts("Accept");
}
}
}
return 0;
}