zoukankan      html  css  js  c++  java
  • hdu 6109 数据分割(并查集,倍增)

    题意:比较绕,n个表达式,表示a==b或者a!=b,有矛盾就重新开始,问可以分成多少段,每段多大。。

    思路:倍增,On判断,也可以并查集加set维护(合并要注意使得集合头要是最早出现的。。),这里提供一下倍增的做法

    PS。顺便吐槽一下百度之星的测评姬。。。还想吐槽一下自己比去年大概还弱,,今年怕是要打铁了

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    #define MEM(a,b) memset(a,b,sizeof(a))
    #define bug puts("bug");
    #define PB push_back
    #define MP make_pair
    #define X first
    #define Y second
    typedef unsigned long long ll;
    typedef pair<int,int> pii;
    const int maxn=1e6+10;
    using namespace std;
    int n,a[maxn],b[maxn],c[maxn];
    int f[maxn];
    int fin(int x){
        if(x==f[x]) return x;
        return f[x]=fin(f[x]);
    }
    int un(int x,int y){
        int fx=fin(x),fy=fin(y);
        if(fx!=fy) f[fx]=fy;
    }
    int ok(int l,int r){
        if(r>=n) return 0;
        int ret=1;
        for(int i=l;i<=r;i++) if(c[i]==1) un(a[i],b[i]);
        for(int i=l;i<=r;i++) if(c[i]==0&&fin(a[i])==fin(b[i])) ret=0;
        for(int i=l;i<=r;i++) f[a[i]]=a[i],f[b[i]]=b[i];
        return ret;
    }
    
    int main(){
        while(scanf("%d",&n)!=EOF){
            for(int i=0;i<n;i++) scanf("%d%d%d",&a[i],&b[i],&c[i]);
            for(int i=0;i<n+10;i++) f[i]=i;
            int l=0;
            vector<int> ans;
            while(l<n){
                int d=1;
                int ll=l;
                while(ok(l,ll+d)){
                   while(ok(l,ll+d*2)) d*=2;
                   ll+=d;
                   d=1;
                }
                if(ll+d<n)ans.PB(ll+d-l+1);
                l=ll+d+1;
            }
            printf("%d
    ",ans.size());
            for(int i=0;i<ans.size();i++)
                printf("%d
    ",ans[i]);
        }
        return 0;
    }
    



  • 相关阅读:
    仙人球的残影
    Calculate the formula
    自定义代码段
    getter-setter方法练习
    封装
    Xcode文档安装
    Xcode模板修改
    匿名对象
    OC多文件开发介绍
    #pragma mark指令
  • 原文地址:https://www.cnblogs.com/zhangxianlong/p/10672504.html
Copyright © 2011-2022 走看看