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; }