【NOI2015】程序自动分析

https://www.luogu.org/problem/show?pid=1955

并查集+离散化。

先执行所有x=y问题,即合并x和y。

再依次执行所有x!=y问题,即查询x和y是否处于同一集合。如果是,则有x=y且x!=y,不满足条件。

如果所有的x!=y都得到满足,这组数据就可以满足。

注意到i,j范围为[1,1e9],并查集数组开不了这么大的范围。又注意到n范围只有[1,1e5],考虑离散化。

先读入所有出现的数字,存到一个数组,然后排序并去重。之后操作用到的数字都在这个数组进行二分查找。

时间复杂度O(nlogn)。

注意的坑:

  • 最多有n个操作,每个操作有两个数字,所以并查集的大小应该是n*2。
#include <algorithm>
#include <cstring>
#include <iostream>
#include <vector>
#define maxn 100005 * 2 // n个操作,每个操作两个数,最多出现n*2个数
using namespace std;
typedef unsigned long long ullint;
namespace djs
{
int parent[maxn];
inline void init()
{
    for (int i = 0; i < maxn; i++)
        parent[i] = -1;
}
inline int find(int x)
{
    if (parent[x] < 0)
        return x;
    else
        return parent[x] = find(parent[x]);
}
inline void merge(int x, int y)
{
    x = find(x);
    y = find(y);
    if (x == y)
        return;
    else
    {
        //令x为rank更大的,即parent值更小的
        if (parent[x] > parent[y])
            swap(x, y);
        parent[x] += parent[y];
        parent[y] = x;
    }
}
inline bool is_related(int x, int y)
{
    return find(x) == find(y);
}
}
typedef pair<ullint, ullint> query;
vector<query> q, m;                  // 暂存查询与合并操作
vector<ullint> data;                 // 存储读入的所有数据
vector<ullint>::iterator unique_end; // 去重后的数据的尾后迭代器
inline int get_pos(ullint v)         // 二分查找v在data所处的位置
{
    return lower_bound(data.begin(), unique_end, v) - data.begin();
}
int main()
{
    ios::sync_with_stdio(false);
    int t;
    cin >> t;
    while (t--)
    {
        int n;
        cin >> n;
        djs::init();
        m.clear();
        q.clear();
        data.clear();

        ullint a, b, c;
        for (int i = 0; i < n; i++)
        {
            cin >> a >> b >> c;
            data.push_back(a);
            data.push_back(b);
            switch (c)
            {
            case 1:
                m.push_back(make_pair(a, b));
                break;

            case 0:
                q.push_back(make_pair(a, b));
                break;
            }
        }

        //离散化
        sort(data.begin(), data.end());
        unique_end = unique(data.begin(), data.end());

        //合并
        for (int i = 0; i < m.size(); i++)
            djs::merge(get_pos(m[i].first), get_pos(m[i].second));

        //查询
        bool yes = true;
        for (int i = 0; i < q.size(); i++)
        {
            if (djs::is_related(get_pos(q[i].first), get_pos(q[i].second)))
            {
                yes = false;
                break;
            }
        }
        if (yes)
            cout << "YES" << endl;
        else
            cout << "NO" << endl;
    }
    return 0;
}
原文地址:https://www.cnblogs.com/ssttkkl/p/7105772.html