zoukankan      html  css  js  c++  java
  • 【做题笔记】洛谷P1955[NOI2015]程序自动分析

    第一道蓝题祭~


    注意到本题中判断的是下标,即,并不是真的判断 (i) 是否等于 (j)

    显然考虑并查集,把所有标记为“相等”的数放在一个集合里,然后最后扫一遍每个数,如果有两个数标记为“不等”但是在一个集合里那么说明不合法,输出 NO ,否则输出 YES

    接下来考虑一些细节

    注意到在所有数据输入完后才需要输出判定结果,所以每次询问是离线的。也就是说,我们只关心这些条件是否冲突,而不关心它们出现的先后次序

    所以将所有标记为“相等”的数先处理,相当于对于每一组标记为“相等”的数据,合并各自所在的并查集

    注意到 (1 leq i,j leq 10^9) ,数据范围很大,所以需要离散化。

    离散化时注意:由于待会在用 lower_bound 查找每个数出现的位置时用的是二分查找,所以必须保证离散数组要排好序


    为什么可以离散化?

    注意到本题只关心每个数被标记为 (1) 还是 (0) ,不关心每个数具体的值,也不需要对一段区间(形如 ([l,r]))进行操作,满足离散化的充要条件


    每次记得把所有数组清空

    需要快读

    需要路径压缩

    参考代码,本题细节较多,稍有不慎就会收获大红大紫大蓝,,

    #include <iostream>
    #include <stdio.h>
    #include <string.h>
    #include <algorithm>
    #define ull unsigned long long
    
    //这题需要unsigned long long
    
    using namespace std;
    
    int t;
    
    struct q
    {
        ull i,j,e;
    };
    q a[10000010];
    
    ull b[1000010*3];
    
    //要开 3 倍!!!
    
    ull f[1000010];
    
    int cmp(q x,q y)
    {
        return x.e>y.e;
    }
    
    int get(ull x)
    {
        if(x==f[x]) return x;
        return f[x]=get(f[x]);
    }
    
    void merge(ull x,ull y)
    {
        f[get(x)]=get(y);
    }
    
    inline int read()
    {
        int w=1,s=0;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
        while(ch>='0'&&ch<='9')s=s*10+ch-'0',ch=getchar();
        return s*w;
    }
    
    int main()
    {
        t=read();
        while(t--)
        {
            int n,ra=0;
            n=read();
            memset(a,0,sizeof(a));
            memset(b,0,sizeof(b));
            memset(f,0,sizeof(f));
            for(int i=1;i<=n;i++)
            {
                a[i].i=read(),a[i].j=read(),a[i].e=read();
                b[++ra]=a[i].i;
                b[++ra]=a[i].j;
                //离散数组 b 存放的实际上是下标(题目中的)
            }
            sort(b+1,b+ra+1);
            int cnt=unique(b+1,b+1+ra)-b; //去重
            for(int i=1;i<=n;i++)
            {
                a[i].i=lower_bound(b+1,b+1+cnt,a[i].i)-b;
                a[i].j=lower_bound(b+1,b+1+cnt,a[i].j)-b;
            }
            for(int i=1;i<=cnt;i++) f[i]=i;
            sort(a+1,a+n+1,cmp); //以是否被标记为相等排序,使待会先处理可以合并的操作
            bool flag=true;
            for(int i=1;i<=n;i++)
            {
                if(a[i].e) merge(a[i].i,a[i].j);
                else if(get(a[i].i)==get(a[i].j))
                {
                    printf("NO
    ");
                    flag=false;
                    break;
                }
            }
            if(flag) printf("YES
    ");
        }
        return 0;
    }
    
  • 相关阅读:
    WebMatrix简介与预览
    使用NuGet增加常见包引用
    用Jquery实现的一个Table的帮助js
    使用AspNetPager进行存储过程分页
    Android之旅AppWidget
    SQL积累
    【问题记录】Asp.net WebApplication和WebSite中用户控件的使用区别
    ActionScript 3.0工厂模式实例
    ActionScript 3.0 实现单态模式
    装饰器模式小结
  • 原文地址:https://www.cnblogs.com/BlueInRed/p/12332448.html
Copyright © 2011-2022 走看看