首页 > 代码库 > 并查集-解决区间和纠错问题 hdu-3038

并查集-解决区间和纠错问题 hdu-3038

题目:多次给出信息,告诉你[a,b]区间的和,求多少个错误信息(错误信息不考虑)。

乍一看有点像线段树,但想想就发现这个并不能用线段树方便地解决。后来经提醒是并查集的一种经典题型。

把区间抽象为并查集的子节点和母根结点,子节点存放了到根节点的区间和。这样当引入一个新的区间,如果区间左右界根节点不同就一定不存在矛盾(有点种类并查集的意思,形象来看就是存在冗余区间用于调整),然后可以通过现存集合推导出子节点到根节点的区间和。如果根节点相同则要判断一下是否矛盾(画个图对线段加加减减就能推出公式了,文字不太好描述)。

#include <iostream>#include <cstdio>#define LL long long intusing namespace std;int pre[200005];LL val[200005];int Find(int x){    if(pre[x]==x) return x;    int te=Find(pre[x]);    val[x]+=val[pre[x]];    return pre[x]=te;}void ini(){    int lx=200000;    for(int i=0;i<=lx;i++)        pre[i]=i,val[i]=0;}int main(){    cin.sync_with_stdio(false);    int n,m;    while(cin>>n>>m)    {        ini();        int u,v,w,ans=0;        for(int i=0;i<m;i++)        {            cin>>u>>v>>w;            u--;            int t[2]={Find(u),Find(v)};            if(t[0]==t[1])            {                if(val[v]-val[u]!=w)                    ans++;            }            else            {                pre[t[1]]=t[0];                val[t[1]]=val[u]-val[v]+w;            }        }        cout<<ans<<endl;    }    return 0;}

 

并查集-解决区间和纠错问题 hdu-3038