题目:

思路:

异或性质 + 经典trick 

遇到环上问题 or 树上问题,我们都可以往链上想

本题就是破环成链,我们将一个线段放在链上,可以发现其连接了两个点,那么如果此后如果加入了一个线段,那么就有以下三种情况(红色线段是最先画的,其余线段是下一个加入的线段的可能情况)

①.新加的线段与原来的线段端点不相交

此时显然是没有相交的

②.新加的线段与原来的线段端点 相交一个

此时就是二者相交了

③.新加的线段与原来的线段端点不相交

此时显然是没有相交的

所以可以想到一个结论:如果新加入的区间之间 包含了 别的区间一个端点,那么此时就是不能加入的

那么如何判断呢?

想想异或的性质,对于偶数个相同的数异或,那么结果就是 0,否则就是这个数本身

所以我们可以利用区间异或和,对于每个线段,如果其可以放,那么就相当于给 l,r 赋值了一个 id 值,那么判断是否相交就是判断 sum[r] ^ sum[l-1] 是否为 0 即可

但是会有特殊情况,如果我们赋值的是操作的 id,那么对于 1 ^ 2 ^ 3 = 0,但是此时是不合法的,因为都有三个线段的各一个端点了,显然相交

为了防止这种情况,我们可以使用异或哈希,即每次赋值的不是操作 id,而是一个随机数,这样就能解决这个问题了

那么对于单点修改 + 区间查询,我们直接上树状数组即可

代码:

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define yes cout << "Yes\n"
#define no cout << "No\n"
mt19937_64 rnd(chrono::steady_clock::now().time_since_epoch().count());

int n;
int bittree[1000006];
int lowbit(int x) { return x & -x; }
void update(int x, int k)
{
    for (; x <= n; x += lowbit(x))
        bittree[x] ^= k;
}
int sum(int x)
{
    int res = 0;
    for (; x; x -= lowbit(x))
        res ^= bittree[x];
    return res;
}
int query(int a, int b)
{
    return sum(b) ^ sum(a - 1);
}
void solve()
{
    int q;
    cin >> n >> q;
    while (q--)
    {
        int a, b;
        cin >> a >> b;
        if (query(a, b) == 0)
        {
            yes;
            int rd = rnd();
            update(a, rd);
            update(b, rd);
        }
        else
        {
            no;
        }
    }
}

signed main()
{
    cin.tie(0)->sync_with_stdio(0);
    int t = 1;
    while (t--)
    {
        solve();
    }
    return 0;
}

Logo

码道开发者社区,聚焦华为云码道 CodeArts 代码智能体,沉淀 Agent、Skill、鸿蒙开发实战内容,供开发者查阅资料、交流技术、分享工程实践

更多推荐