题目链接

传送门

题意

给你\(n\)堆石子,每堆有\(a_i\)堆石子,\(q\)次操作:

  • 在\([L,R]\)内有多少个子区间使得\(Alice\)(先手)在\(Nim\)博弈中获胜;
  • 交换\(a_{pos},a_{pos+1}\)的值。

思路

这题和cf617E差不多。

首先我们知道以下性质:

  • \(Nim\)博弈只有当所有石子数异或为\(0\)才会导致先手必败;
  • 在预处理前缀异或和后,交换相邻两堆石子的石子数只会影响\(pos\)处的值。

因此我们在预处理出前缀异或和后就可以用待修改莫队来解决本题,我们用\(cnt\)数组来处理出区间内\(x\)出现次数,\(sum\)表示区间内有多少个子区间异或和为\(0\),那么最后答案为\(\frac{(R-L+1)(R-L)}{2}-sum\)。

代码实现如下

#include <set>
#include <map>
#include <deque>
#include <queue>
#include <stack>
#include <cmath>
#include <ctime>
#include <bitset>
#include <cstdio>
#include <string>
#include <vector>
#include <cassert>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <unordered_map>
using namespace std; typedef long long LL;
typedef pair<LL, LL> pLL;
typedef pair<LL, int> pLi;
typedef pair<int, LL> pil;;
typedef pair<int, int> pii;
typedef unsigned long long uLL; #define lson rt<<1
#define rson rt<<1|1
#define lowbit(x) x&(-x)
#define name2str(name) (#name)
#define bug printf("*********\n")
#define debug(x) cout<<#x"=["<<x<<"]" <<endl
#define FIN freopen("D://Code//in.txt","r",stdin)
#define IO ios::sync_with_stdio(false),cin.tie(0) const double eps = 1e-8;
const int mod = 1000000007;
const int maxn = 1e5 + 7;
const double pi = acos(-1);
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3fLL; int n, q, op, l, r, block;
LL sum;
int a[maxn], b[maxn];
LL cnt[1<<20+5]; struct que {
int l, r, id, t;
LL ans;
bool operator < (const que& x) const {
if((l - 1) / block != (x.l - 1) / block) {
return l < x.l;
}
if((r - 1) / block != (x.r - 1) / block) {
return r < x.r;
}
return t < x.t;
}
}ask[maxn]; struct modify {
int pre, val, pos;
}mfy[maxn]; void del(int x) {
--cnt[x];
sum -= cnt[x];
} void add(int x) {
sum += cnt[x];
++cnt[x];
} int main() {
#ifndef ONLINE_JUDGE
FIN;
#endif // ONLINE_JUDGE
while(~scanf("%d%d", &n, &q)) {
sum = 0;
for(int i = 0; i <= 1024 * 1024; ++i) cnt[i] = 0;
for(int i = 1; i <= n; ++i) {
scanf("%d", &a[i]);
b[i] = b[i-1] ^ a[i];
}
block = (int)pow(n, 2.0 / 3);
int nw = 0, idq = 0, idc = 0;
for(int i = 1; i <= q; ++i) {
scanf("%d", &op);
if(op == 1) {
idq++;
scanf("%d%d", &ask[idq].l, &ask[idq].r);
ask[idq].id = idq;
--ask[idq].l;
ask[idq].t = nw;
} else {
idc++;
++nw;
scanf("%d", &mfy[idc].pos);
int pos = mfy[idc].pos;
mfy[idc].pre = b[pos];
mfy[idc].val = b[pos+1] ^ a[pos];
b[pos] = b[pos+1] ^ a[pos];
swap(a[pos], a[pos+1]);
}
}
sort(ask + 1, ask + idq + 1);
int tmp = nw;
for(int i = 1, l = 1, r = 0; i <= idq; ++i) {
while (r < ask[i].r) add(b[++r]);
while (l > ask[i].l) add(b[--l]);
while (r > ask[i].r) del(b[r--]);
while (l < ask[i].l) del(b[l++]);
while (tmp < ask[i].t) {
tmp++;
if (mfy[tmp].pos >= ask[i].l && mfy[tmp].pos <= ask[i].r) {
del(mfy[tmp].pre);
add(mfy[tmp].val);
}
b[mfy[tmp].pos] = mfy[tmp].val;
}
while (tmp > ask[i].t) {
if (mfy[tmp].pos >= ask[i].l && mfy[tmp].pos <= ask[i].r) {
del(mfy[tmp].val);
add(mfy[tmp].pre);
}
b[mfy[tmp].pos] = mfy[tmp].pre;
tmp--;
}
ask[ask[i].id].ans = 1LL * (ask[i].r - ask[i].l) * (ask[i].r - ask[i].l + 1) / 2 - sum;
}
for(int i = 1; i <= idq; ++i) {
printf("%lld\n", ask[i].ans);
}
}
return 0;
}

2019年杭电多校第三场 1008题Game(HDU6610+带修改莫队+Nim博弈)的更多相关文章

  1. 2019年杭电多校第三场 1011题Squrirrel(HDU6613+树DP)

    题目链接 传送门 题意 给你一棵无根树,要你寻找一个根节点使得在将一条边权变为\(0\)后,离树根最远的点到根节点的距离最小. 思路 本题和求树的直径很像,不过要记得的东西有点多,且状态也很多. \( ...

  2. [2019杭电多校第三场][hdu6609]Find the answer(线段树)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6609 大致题意是求出每个位置i最小需要将几个位置j变为0(j<i),使得$\sum_{j=1}^ ...

  3. [2019杭电多校第三场][hdu6608]Fansblog

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6608 大致题意是比p小的最大素数q,求q!%p的值. 由威尔逊定理开始推: $(p-1)!\equiv ...

  4. [2019杭电多校第三场][hdu6606]Distribution of books(线段树&&dp)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6606 题意为在n个数中选m(自选)个数,然后把m个数分成k块,使得每块数字之和最大的最小. 求数字和最 ...

  5. 2019杭电多校第三场hdu6608 Fansblog(威尔逊定理)

    Fansblog 题目传送门 解题思路 Q! % P = (P-1)!/(P-1)...(Q-1) % P. 因为P是质数,根据威尔逊定理,(P-1)!%P=P-1.所以答案就是(P-1)((P-1) ...

  6. 2019杭电多校第三场hdu6609 Find the answer(线段树)

    Find the answer 题目传送门 解题思路 要想变0的个数最少,显然是优先把大的变成0.所以离散化,建立一颗权值线段树,维护区间和与区间元素数量,假设至少减去k才能满足条件,查询大于等于k的 ...

  7. 2019杭电多校第三场hdu6606 Distribution of books(二分答案+dp+权值线段树)

    Distribution of books 题目传送门 解题思路 求最大值的最小值,可以想到用二分答案. 对于二分出的每个mid,要找到是否存在前缀可以份为小于等于mid的k份.先求出这n个数的前缀和 ...

  8. 2018 Multi-University Training Contest 3 杭电多校第三场

    躺了几天 终于记得来填坑了 1001 Ascending Rating   (hdoj 6319) 链接:http://acm.hdu.edu.cn/showproblem.php?pid=6319 ...

  9. 杭电多校第三场 A Ascending Rating

    Problem Description Before the start of contest, there are n ICPC contestants waiting in a long queu ...

随机推荐

  1. Flume+Kafka+Storm+Redis 大数据在线实时分析

    1.实时处理框架 即从上面的架构中我们可以看出,其由下面的几部分构成: Flume集群 Kafka集群 Storm集群 从构建实时处理系统的角度出发,我们需要做的是,如何让数据在各个不同的集群系统之间 ...

  2. 哈夫曼树的构建(C语言)

    哈夫曼树的构建(C语言) 算法思路: 主要包括两部分算法,一个是在数组中找到权值最小.且无父结点两个结点位置,因为只有无父结点才能继续组成树: ​ 另一个就是根据这两个结点来修改相关结点值. 结构定义 ...

  3. java的this关键字

    class point{ int x; int y; point(int x,int y){ this.x=x;//如果形参和属性名相同,为了区分开来,必须要在属性名前加this y=y;//若不加t ...

  4. CentOS7使用tar.gz包安装MySql的踩坑之旅

    由于客户的CentOS服务器没有安装yum工具,只能通过下载tar.gz包安装mysql,于是跟着万能的百度开启了漫漫踩坑之旅: 1.下载mysql-5.6.33-linux-glibc2.5-x86 ...

  5. 一个萝卜一个坑#我的C坑_两局变量

    前面的笔记慢慢补 全局变量和局部变量的区别: 1.首字母 尽量不用全局变量原因: 1.占内存 2.降低通用性和可靠性 3.降清晰度 若在同一源文件中,全局变量和局部变量同名,记住很重要的一条:实参决定 ...

  6. 【题解】【网络流24题】航空路线问题 [P2770] [Loj6122]

    [题解][网络流24题]航空路线问题 [P2770] [Loj6122] 传送门:航空路线问题 \([P2770]\) \([Loj6122]\) [题目描述] 给出一张有向图,每个点(除了起点 \( ...

  7. 《即时消息技术剖析与实战》学习笔记3——IM系统如何保证消息的实时性

    IM 技术经历过几次迭代升级,如图所示: 从简单.低效的短轮询逐步升级到相对效率可控的长轮询: 全双工的 Websocket 彻底解决了服务端的推送问题: 基于 TCP 长连接衍生的 IM 协议,能够 ...

  8. C#生成唯一不重复订单号帮助类

    1.使用场景 通常,在做一些表单的功能时,需要生成唯一不重复的订单单号,本文提供的帮助类可以适合大多数场景的单号生成使用,拿来即用,方便快捷无重复.而且,在高并发的情况下也是可以使用的. 之前看到有人 ...

  9. 突破Java面试-Redis集群模式的原理

    1 面试题 Redis集群模式的工作原理说一下?在集群模式下,key是如何寻址的?寻址都有哪些算法?了解一致性hash吗? 2 考点分析 Redis不断在发展-Redis cluster集群模式,可以 ...

  10. NodeJS新建服务器以及CommonJS规范

    1.什么是node.js?(1)Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境.Node.js 使用了一个事件驱动.非阻塞式 I/O 的模型,使其轻量又高效.( ...