Codeforces Round 943 (Div. 3) F. Equal XOR Segments 前缀异或+二分查找

Equal XOR Segments

题目描述

如果可以将数组分成 k > 1 k>1 k>1 部分,使得每部分的值 bitwise XOR 都相等,那么我们就称该数组 x 1 , … , x m x_1,\dots,x_m x1,,xm 为有意思的数组。

更正式地说,你必须把数组 x x x 分成 k k k 个连续的部分, x x x 中的每个元素都必须准确地属于 1 1 1 个部分。设 y 1 , … , y k y_1,\dots,y_k y1,,yk 分别是各部分元素的 XOR。那么 y 1 = y 2 = ⋯ = y k y_1=y_2=\dots=y_k y1=y2==yk 必须满足。

例如,如果是 x = [ 1 , 1 , 2 , 3 , 0 ] x = [1, 1, 2, 3, 0] x=[1,1,2,3,0] ,可以将其拆分如下: [ 1 ] , [ 1 ] , [ 2 , 3 , 0 ] [\color{blue}1], [\color{green}1], [\color{red}2, \color{red}3, \color{red}0] [1],[1],[2,3,0] 。其满足 1 = 1 = 2 ⊕ 3 ⊕ 0 \color{blue}1=\color{green}1=\color{red}2 \oplus \color{red}3\oplus \color{red}0 1=1=230 ,是有意思的数组。

给你一个数组 a 1 , … , a n a_1,\dots,a_n a1,,an 。你的任务是回答 q q q 个查询:

  • 对于固定的 l l l , r r r , 判断子数组 a l , a l + 1 , … , a r a_l,a_{l+1},\dots,a_r al,al+1,,ar 是否有趣。

输入描述

第一行包含一个整数 t t t ( 1 ≤ t ≤ 1 0 4 1\le t\le 10^4 1t104 ) - 测试用例数。

每个测试用例的第一行包含两个整数 n n n q q q ( 2 ≤ n ≤ 2 ⋅ 1 0 5 2 \le n \le 2 \cdot 10^5 2n2105 , 1 ≤ q ≤ 2 ⋅ 1 0 5 1 \le q \le 2 \cdot 10^5 1q2105 )–分别是数组中的元素个数和查询次数。

下一行包含 n n n 个整数 a 1 , … , a n a_1,\dots,a_n a1,,an ( 0 ≤ a i < 2 30 0 \le a_i < 2^{30} 0ai<230 ) - 数组元素。

接下来的每行 q q q 包含两个整数 l l l r r r ( 1 ≤ l < r ≤ n 1 \le l < r \le n 1l<rn ),分别描述查询。

保证所有测试用例中 n n n 的总和不超过 2 ⋅ 1 0 5 2 \cdot 10^5 2105

保证所有测试用例中 q q q 的总和不超过 2 ⋅ 1 0 5 2 \cdot 10^5 2105

输出描述

对于每个查询,如果子数组有趣,则输出一行 “YES”,否则输出一行 “NO”。

样例输入

4
5 5
1 1 2 3 0
1 5
2 4
3 5
1 3
3 4
5 5
1 2 3 4 5
1 5
2 4
3 5
1 3
2 3
7 4
12 9 10 9 10 11 9
1 5
1 7
2 6
2 7
11 4
0 0 1 0 0 1 0 1 1 0 1
1 2
2 5
6 9
7 11

样例输出

YES
YES
NO
NO
NO

YES
NO
NO
YES
NO

NO
NO
NO
NO

YES
NO
YES
YES

原题

CF——传送门

代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);

    int t;
    cin >> t;
    while (t--)
    {
        int n, q;
        cin >> n >> q;
        vector<int> a(n + 1);
        for (int i = 1; i <= n; i++)
        {
            cin >> a[i];
        }
        // b数组为a的前缀位异或
        vector<int> b(n + 1, 0);
        // 用map离散存储等于某值的所有索引位置
        map<int, vector<int>> idx;
        idx[0].push_back(0);
        for (int i = 1; i <= n; i++)
        {
            b[i] = b[i - 1] ^ a[i];
            idx[b[i]].push_back(i);
        }
        // 处理询问
        int l, r;
        while (q--)
        {
            cin >> l >> r;
            // 假如k=2,则需要b[l-1]^b[t]==b[t]^b[r]即b[l-1]==b[r]
            if (b[l - 1] == b[r])
            {
                cout << "YES" << '\n';
                continue;
            }
            // 假如k=3,则需要b[l-1]^b[s]==b[s]^b[t]==b[t]^b[r]即b[l-1]==b[t]且b[s]==b[r]
            // 问题转化为找出两点s,t满足l<=s<t<r,b[l-1]==b[t]且b[s]==b[r]
            // 二分查找值等于b[r]中的大于l-1位置的位置
            int s = lower_bound(idx[b[r]].begin(), idx[b[r]].end(), l) - idx[b[r]].begin();
            if (s == idx[b[r]].size() || idx[b[r]][s] >= r) // 没找到或者找到的位置大于等于r,都不满足
            {
                cout << "NO" << '\n';
                continue;
            }
            // 既然已找到s的位置,那么二分查找值等于b[l-1]中的大于s位置的位置
            int t = lower_bound(idx[b[l - 1]].begin(), idx[b[l - 1]].end(), idx[b[r]][s] + 1) - idx[b[l - 1]].begin();
            if (t == idx[b[l - 1]].size() || idx[b[l - 1]][t] >= r) // 没找到或者找到的位置大于等于r,都不满足
            {
                cout << "NO" << '\n';
            }
            else
            {
                cout << "YES" << '\n';
            }
        }
        cout << '\n';
    }

    return 0;
}
### Codeforces Round 927 Div. 3 比赛详情 Codeforces是一个面向全球程序员的比赛平台,定期举办不同级别的编程竞赛。Div. 3系列比赛专为评级较低的选手设计,旨在提供更简单的问题让新手能够参与并提升技能[^1]。 #### 参赛规则概述 这类赛事通常允许单人参加,在规定时间内解决尽可能多的问题来获得分数。评分机制基于解决问题的速度以及提交答案的成功率。比赛中可能会有预测试案例用于即时反馈,而最终得分取决于系统测试的结果。此外,还存在反作弊措施以确保公平竞争环境。 ### 题目解析:Moving Platforms (G) 在这道题中,给定一系列移动平台的位置和速度向量,询问某时刻这些平台是否会形成一条连续路径使得可以从最左端到达最右端。此问题涉及到几何学中的线段交集判断和平面直角坐标系内的相对运动分析。 为了处理这个问题,可以采用如下方法: - **输入数据结构化**:读取所有平台的数据,并将其存储在一个合适的数据结构里以便后续操作。 - **时间轴离散化**:考虑到浮点数精度误差可能导致计算错误,应该把整个过程划分成若干个小的时间间隔来进行模拟仿真。 - **碰撞检测算法实现**:编写函数用来判定任意两个矩形之间是否存在重叠区域;当发现新的连接关系时更新可达性矩阵。 - **连通分量查找技术应用**:利用图论知识快速求解当前状态下哪些节点属于同一个集合内——即能否通过其他成员间接相连。 最后输出结果前记得考虑边界条件! ```cpp // 假设已经定义好了必要的类和辅助功能... bool canReachEnd(vector<Platform>& platforms, double endTime){ // 初始化工作... for(double currentTime = startTime; currentTime <= endTime ;currentTime += deltaT){ updatePositions(platforms, currentTime); buildAdjacencyMatrix(platforms); if(isConnected(startNode,endNode)){ return true; } } return false; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值