首页 > 其他分享 >洛谷P6225异或橙子

洛谷P6225异或橙子

时间:2024-11-20 23:20:30浏览次数:1  
标签:dots 洛谷 P6225 int 贡献 异或 区间 oplus id

洛谷P6225 异或橙子

位运算 思维 树状数组

这是题面

思路

先看一下这个式子要干什么

例如 \(l=2,u=4\) 的情况,记橙子序列 \(A\) 中第 \(i\) 个橙子的整数是 \(a_i\),那么他要求的就是:

\[a_2 \oplus a_3 \oplus a_4 \oplus (a_2\oplus a_3)\oplus(a_3\oplus a_4)\oplus(a_2\oplus a_3 \oplus a_4) \]

也就是说,对于每一个连续的区间,我们都要或一下,注意一共有\(\frac{n(n + 1)}{2}\)个区间,暴力遍历是\(O(n^2)\)的复杂度肯定会超时

对于这样的所有连续的区间的问题,我们可以考虑每一个元素的贡献是多少。因为是异或运算,所以如果一个元素贡献的次数是偶数次的话相当于没有这个数,贡献的次数是奇数的话相当于就出现了一次

现在我们来看每个元素贡献了多少次

\(a_1, a_2, a_3, a_4, a_5 \dots a_n\)

  1. \(a_1\)贡献的区间有\((a_1), (a_1, a_2), (a_1, a_2, a_3), \dots (a_1, a_2, a_3 \dots a_n)\), \(a_1\)贡献了\(n\)次

  2. \(a_2\)贡献的区间有\((a_2), (a_2, a_3), (a_2, a_3, a_4), \dots (a_2, a_3, a_4 \dots a_n)\), 有\(n - 2\), 再加上\(a_1\)贡献的区间中包含\(a_2\)的,一共是\((n - 1) * 2\)个\(\dots\),以此类推,对于一个位置\(i\),会贡献\((n - i + 1) * i\)次

接着我们还能发现,如果区间长度为偶数时,贡献的次数全都是偶数,结果直接就是\(0\),区间长度为奇数时,当\(left\)(区间左端点)为奇数时,只有奇数位置有贡献,否则就只有偶数位置有贡献

用两个树状数组分别维护偶数位置和奇数位置就好了

代码

#include <bits/stdc++.h>
#define endl '\n'
#define int long long
#define lowbit(x) x & -x
const int maxn = 2e5 + 5;
const int inf = 0x7f7f7f7f;
const int mx = 2e5 + 1;
struct custom_hash 
{
	static uint64_t splitmix64(uint64_t x) 
    {
		x ^= x << 13;
		x ^= x >> 7;
		x ^= x << 17;
		return x; 
	}
	size_t operator () (uint64_t x) const 
    {
		static const uint64_t FIXED_RANDOM = std::chrono::steady_clock::now().time_since_epoch().count(); // 时间戳
		return splitmix64(x + FIXED_RANDOM);
	}
};

// a1, a2, a3, ....... , an有n个数,这 n * (n - 1) / 2 个区间中每一个元素被算了几次

int fenwick1[maxn], fenwick2[maxn];

// fenwick1 奇数位置

// fenwick2 偶数位置

void modify(int t[], int pos, int v)
{
    while(pos <= mx)
    {
        t[pos] ^= v;
        pos += lowbit(pos);
    }
}

int query(int pos, int t[])
{
    int res = 0;
    while(pos)
    {
        res ^= t[pos];
        pos -= lowbit(pos);
    }
    return res;
}

int single_query(int pos, int t[])
{
    return query(pos, t) ^ query(pos - 1, t);
}

int range_query(int l, int r, int t[])
{
    return query(r, t) ^ query(l - 1, t);
}

void solve()
{
    int odd = 0, even = 0;
    int n = 0, m = 0;
    std::cin >> n >> m;
    int tmp = 0;
    for (int i = 1; i <= n; i++)
    {
        std::cin >> tmp;
        if (i & 1)
        {
            modify(fenwick1, ++odd, tmp);
        }
        else
        {
            modify(fenwick2, ++even, tmp);
        }
    }
    int op = 0, x = 0, y = 0;
    for (int i = 1; i <= m; i++)
    {
        std::cin >> op >> x >> y;
        if (op == 1)
        {
            int id = 0;
            if (x & 1)
            {
                id = x / 2 + 1;
                int delta = y ^ single_query(id, fenwick1);
                modify(fenwick1, id, delta);
            }
            else
            {
                id = x / 2;
                int delta = y ^ single_query(id, fenwick2);
                modify(fenwick2, id, delta);
            }
        }
        else
        {
            int tot = y - x + 1;
            if (tot & 1)
            {
                if (x & 1)
                {
                    int id1 = x / 2 + 1, id2 = y / 2 + 1;
                    std::cout << range_query(id1, id2, fenwick1) << endl;
                }
                else
                {
                    int id1 = x / 2, id2 = y / 2;
                    std::cout << range_query(id1, id2, fenwick2) << endl;
                }
            }
            else
            {
               std::cout << 0 << endl;
            }
        }
    }
}

signed main()
{
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr); std::cout.tie(nullptr);
    //freopen("out.txt", "w", stdout);
    int t = 1;
    //std::cin >> t;
    while(t--)
    {
        solve();
    }
    return 0;
}

标签:dots,洛谷,P6225,int,贡献,异或,区间,oplus,id
From: https://www.cnblogs.com/SteinsGateSg/p/18559606

相关文章

  • 洛谷算法题P1307 [NOIP2011 普及组] 数字反转
    题目题目描述给定一个整数N,请将该数各个位上数字反转得到一个新数。新数也应满足整数的常见形式,即除非给定的原数为零,否则反转后得到的新数的最高位数字不应为零(参见样例2)。输入格式一个整数N。输出格式一个整数,表示反转后的新数。样例#1样例输入#1123样例输......
  • 洛谷 P11210 强制在线动态二维数点
    题目传送门题目中的点满足\(y\lex\),那么不妨把每个点看成区间\([y,x]\)。那么题目相当于要求维护若干个区间,支持修改,以及查询询问区间中区间长度的最小值。从“区间长度的最小值”入手。显然包含别的区间的区间不能成为答案。排除了这样的区间,剩下区间按左端点升序排序,则右端......
  • 洛谷 P1613 跑路 做题记录
    前置芝士:最短路、floyd传递闭包、倍增思路看到题目里面的一次能走\(2^k\)千米,我们联想到倍增,因为只能用跑路器。我们枚举\(k\),然后做一次传递闭包,\((i,j)\)走\(2^k\)千米是相连的,当且仅当有一个点\(k\)是的\((i,k),(k,j)\)可以通过走\(2^{k-1}\)千米相连。此时,\((......
  • 【题解】洛谷:P8593 「KDOI-02」一个弹的投
    P8593「KDOI-02」一个弹的投物理题。首先你要搞懂什么时候会炮弹碰撞,结论:y坐标相同时,水平位置\(x_i\lex_j\)且落点满足\(d_i\ged_j\),两炮弹必然碰撞。但是为什么呢,像我这种完全没学高中物理的伪高中生就不会了,下落时每个物体的相对的高度差是不变的,因为根据伽利略运动独......
  • 【洛谷】P1914 小书童——凯撒密码
    题目背景某蒟蒻迷上了“小书童”,有一天登陆时忘记密码了(他没绑定邮箱or手机),于是便把问题抛给了神犇你。题目描述蒟蒻虽然忘记密码,但他还记得密码是由一个字符串组成。密码是由原文字符串(由不超过50个小写字母组成)中每个字母向后移动 n 位形成的。z 的下一个字母是 ......
  • 洛谷题单指南-二叉堆与树状数组-P2161 [SHOI2009] 会场预约
    原题链接:https://www.luogu.com.cn/problem/P2161题意解读:本题前面形式化描述已经足够清晰。解题思路:要判断线段之间是否有冲突(包含或者交叉),可以借助set,参考:https://www.cnblogs.com/jcwy/p/18447333只不过这里要统计冲突的数量,也就是允许相等的元素重复存在,可以借助multiset......
  • 洛谷:P1008 [NOIP1998 普及组] 三连击
    这道题需要我们找出所有符合要求的数对,由于数据量不大,这里我们可以使用枚举的方法进行枚举,那么我们从最小的三位数100到最大数999进行遍历寻找,再对这三个数进行判断,判断这三个数的每一位是否由1-9这9个数组成,且每个数只出现一次。在判断这个地方我们可以用一个数组来进行计数,将......
  • 洛谷题单指南-二叉堆与树状数组-P5677 [GZOI2017] 配对统计
    原题链接:https://www.luogu.com.cn/problem/P5677题意解读:所谓好的配对,通过分析公式∣ax−ay∣≤∣ax−ai∣(i≠x),可以得知就是一个ax与其差的绝对值最小的形成的配对,在数轴上就是距离ax最近的点ay,配对是下标(x,y),给定若干个区间[l,r],每个区间的配对数*区间编号的累加。解题思路:......
  • 【题解】洛谷:P4805 [CCC2016] 合并饭团
    P4805[CCC2016]合并饭团希望写完这篇题解能真正地会这种题。合并两个的操作很像合并石子的操作,确实直接那么做就可以,但三个怎么办呢,暴力做法就是枚举中间两个端点然后转移,但是这样复杂度太大了有\(O(n^4)\)。于是搬出我们的双指针,在面对区间问题时双指针可以有效地解决问题,......
  • 洛谷P1816忠诚
    洛谷P1816忠诚思路查询区间最小值,\(ST\)表/线段树板子题代码#include<bits/stdc++.h>#defineendl'\n'#defineintlonglongconstintmaxn=2e5+5;constintinf=0x7f7f7f7f;structcustom_hash{ staticuint64_tsplitmix64(uint64_tx){ x^=......