P1955 [NOI2015]程序自动分析 - 并查集+离散化

传送门

60%~70% 裸的并查集,对于每个x=y操作,直接合并x与y所在集合;对于每个x!=y操作,判断x与y的关系,若出现矛盾,输出NO,若所有约束条件都能满足,输出YES。

100% 将所有x和y离散化,然后按上一问做即可。

Tips:

1.需要离散化的数最多有2*n个,数组别开小!!

2.可以优先处理x=y的操作,当然也可以不排序。。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int sz=100000+100;
typedef long long ll;
int fa[sz<<1];
int find(int x){
    return fa[x]==x?x:fa[x]=find(fa[x]);
}
int n;
struct node{
    ll a;
    ll b;
    int e;
}q[sz];
ll num[sz<<1];
ll now[sz<<1],tot;
void rec(){
    sort(num+1,num+(n<<1)+1);
    for(int i=1;i<=(n<<1);i++)
        if(i==1||num[i]!=num[i-1])
            now[++tot]=num[i];
}
int ask(ll x){
    return lower_bound(now+1,now+tot+1,x)-now;
}
bool cmp(node a,node b){
    return a.e>b.e;
}
int main(){
    int t;
    scanf("%d",&t);
    while(t--){
        tot=0;
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            ll a,b;
            int e;
            scanf("%lld%lld%d",&a,&b,&e);
            q[i]=(node){a,b,e};
            num[i]=a;
            num[i+n]=b;
        }
        rec();
        for(int i=1;i<=tot;i++)
            fa[i]=i;
        int k=0;
        sort(q+1,q+n+1,cmp);
        for(int i=1;i<=n;i++){
            int u=ask(q[i].a),v=ask(q[i].b),w=q[i].e;
            if(w){
                fa[find(u)]=find(v);
            }    
            else{
                if(find(u)==find(v)){
                    k=1;break;
                }
            } 
        }
        if(!k)printf("YES\n");
        else printf("NO\n");
    }
    return 0;
}

离散化板子:

ll num[sz<<1];
ll now[sz<<1],tot;
void rec(){
    sort(num+1,num+(n<<1)+1);
    for(int i=1;i<=(n<<1);i++)
        if(i==1||num[i]!=num[i-1])//判重 
            now[++tot]=num[i];
}
int ask(ll x){//查询 
    return lower_bound(now+1,now+tot+1,x)-now;
}

猜你喜欢

转载自www.cnblogs.com/Loi-Brilliant/p/9108168.html