传送门:https://loj.ac/problem/6100

【题解】

我们考虑维护从某个端点开始的最长满足条件的长度,如果知道了这个东西显然我们可以用主席树来对每个节点建棵关于右端点的权值线段树,然后区间修改,标记永久化,询问就可以差分了

考虑如何求出某个端点开始的最长满足条件的长度,也就是某个端点$i$开始,到nxt[i]的这一段都满足异或不减性质。

考虑异或什么时候会导致减法:修改了最高位的时候

我们令s[x][i][j]表示$1 \sim i$个位置,二进制下第j位被当做最高位的时候,被操作了几次,$x$为0或1。0表示原来是1,变成0的次数;1表示原来是0,变成1的次数。

那么我们每次找出最高位就能更新了。

我们还要维护一个前缀异或值来进行操作。

然后我们二分右端点,考虑如何判断区间$[l,r]$是否合法。

对于某一位,如果在$l-1$的时候,前缀异或值为1,那么从$l$开始,相当于没有这个前缀异或值,也就是当修改从0改成1的时候,由于我们是假装他有“1”的前缀异或值,来进行s的操作的,所以s从0改成1相当于实际的1改成0,也就是减小。

同理对于在$l-1$的时候,前缀异或值为0,也进行类似操作判断即可。

那么这个复杂度是$O(logn)$的,因为有log位要判断。

预处理复杂度$O(nlog^2n)$

挺好写的吧。。

# include <stdio.h>
# include <string.h>
# include <iostream>
# include <algorithm> using namespace std; typedef long long ll;
typedef unsigned long long ull;
typedef long double ld; const int M = 2e5 + , N = 1e5 + ;
const int mod = 1e9 + , Max = 5e6 + ; int n, a[N], nxt[N];
int s[][N][], sxor[N];
// 前i个数,第j位为最高位的时候,有多少次从1变成0 (1),以及从0变成1 (0). # define bit(x, i) (((x) >> (i)) & )
# define len(l, r) ((r) - (l) + ) inline bool chk(int l, int r) {
for (int i=; ~i; --i) {
if(bit(sxor[l-], i) && s[][r][i] - s[][l-][i] > ) return false;
if(!bit(sxor[l-], i) && s[][r][i] - s[][l-][i] > ) return false;
}
return true;
} inline bool chk_force(int l, int r) {
int cur, lst; cur = lst = ;
for (int i=l; i<=r; ++i) {
cur = lst ^ a[i];
if(cur < lst) return false;
lst = cur;
}
return true;
} inline int gh(int x) {
for (int i=; ~i; --i)
if(bit(x, i)) return i;
return -;
} inline int gnext(int pos) {
int l=pos, r=n, mid;
while() {
if(r-l <= ) {
for (int i=r; i>=l; --i)
if(chk(pos, i)) return i;
break;
}
mid = l+r>>;
if(chk(pos, mid)) l = mid;
else r = mid;
}
return -;
} int rt[M];
struct CMT {
int ch[Max][], tag[Max], siz;
ll s[Max]; # define ls ch[x][]
# define rs ch[x][] inline void set() {
siz = ;
memset(tag, , sizeof tag);
memset(s, , sizeof s);
} inline void edt(int &x, int y, int l, int r, int L, int R, int d) {
x = ++siz; ch[x][] = ch[y][], ch[x][] = ch[y][];
s[x] = s[y]; tag[x] = tag[y];
if(L == l && r == R) {
tag[x] += d;
return ;
}
s[x] += (ll)d * (R-L+);
int mid = l+r>>;
if(R <= mid) edt(ls, ch[y][], l, mid, L, R, d);
else if(L > mid) edt(rs, ch[y][], mid+, r, L, R, d);
else edt(ls, ch[y][], l, mid, L, mid, d), edt(rs, ch[y][], mid+, r, mid+, R, d);
} inline ll query(int x, int y, int l, int r, int L, int R) {
ll ret = (ll)(tag[y] - tag[x]) * (R-L+);
if(L == l && r == R) return ret + s[y] - s[x];
int mid = l+r>>;
if(R <= mid) return ret + query(ls, ch[y][], l, mid, L, R);
else if(L > mid) return ret + query(rs, ch[y][], mid+, r, L, R);
else return ret + query(ls, ch[y][], l, mid, L, mid) + query(rs, ch[y][], mid+, r, mid+, R);
}
}T; int main() {
cin >> n; sxor[] = ;
for (int i=, h; i<=n; ++i) {
scanf("%d", a+i); sxor[i] = sxor[i-] ^ a[i];
for (int j=; j<=; ++j) s[][i][j] = s[][i-][j], s[][i][j] = s[][i-][j];
h = gh(a[i]);
if(h != -) {
if(bit(sxor[i-], h)) s[][i][h] ++;
else s[][i][h] ++;
}
} for (int i=; i<=n; ++i) nxt[i] = gnext(i); T.set();
for (int i=; i<=n; ++i) T.edt(rt[i], rt[i-], , n, i, nxt[i], ); int Q; cin >> Q;
ll lst = ; int l, r;
while(Q--) {
scanf("%d%d", &l, &r);
l = (l+lst)%n+, r = (r+lst)%n+;
if(l>r) swap(l, r);
lst = T.query(rt[l-], rt[r], , n, l, r);
printf("%lld\n", lst);
lst %= n;
} return ;
}

loj6100 「2017 山东二轮集训 Day1」第一题的更多相关文章

  1. loj6102 「2017 山东二轮集训 Day1」第三题

    传送门:https://loj.ac/problem/6102 [题解] 贴一份zyz在知乎的回答吧 https://www.zhihu.com/question/61218881 其实是经典问题 # ...

  2. LOJ6102「2017 山东二轮集训 Day1」第三题 【min-max容斥,反演】

    题目描述:输入一个大小为\(n\)的集合\(S\),求\(\text{lcm}_{k\in S}f_k\),其中\(f_k\)是第$$个Fibonacci数. 数据范围:\(n\le 5\times ...

  3. 【LOJ#6066】「2017 山东一轮集训 Day3」第二题(哈希,二分)

    [LOJ#6066]「2017 山东一轮集训 Day3」第二题(哈希,二分) 题面 LOJ 题解 要哈希是很显然的,那么就考虑哈希什么... 要找一个东西可以表示一棵树,所以我们找到了括号序列. 那么 ...

  4. LOJ #6119. 「2017 山东二轮集训 Day7」国王

    Description 在某个神奇的大陆上,有一个国家,这片大陆的所有城市间的道路网可以看做是一棵树,每个城市要么是工业城市,要么是农业城市,这个国家的人认为一条路径是 exciting 的,当且仅当 ...

  5. loj6119 「2017 山东二轮集训 Day7」国王

    题目描述 在某个神奇的大陆上,有一个国家,这片大陆的所有城市间的道路网可以看做是一棵树,每个城市要么是工业城市,要么是农业城市,这个国家的人认为一条路径是 exciting 的,当且仅当这条路径上的工 ...

  6. [LOJ#6066]. 「2017 山东一轮集训 Day3」第二题[二分+括号序列+hash]

    题意 题目链接 分析 首先二分,假设二分的答案为 \(mid\),然后考虑利用括号序列来表示树的形态. 点 \(u\) 的 \(k-\) 子树的括号序列表示实际上是刨去了 \(u\) 子树内若干个与 ...

  7. LOJ6066:「2017 山东一轮集训 Day3」第二题

    传送门 二分答案 \(k\),考虑如何 \(hash\) 使得做起来方便 把每个点挂在 \(k+1\) 级祖先上,考虑在祖先上删除 这道题巧妙在于其可以对于 \(dfs\) 序/括号序列 \(hash ...

  8. LOJ 6060「2017 山东一轮集训 Day1 / SDWC2018 Day1」Set(线性基,贪心)

    LOJ 6060「2017 山东一轮集训 Day1 / SDWC2018 Day1」Set $ solution: $ 这一题的重点在于优先级问题,我们应该先保证总和最大,然后再保证某一个最小.于是我 ...

  9. 【LOJ6077】「2017 山东一轮集训 Day7」逆序对 生成函数+组合数+DP

    [LOJ6077]「2017 山东一轮集训 Day7」逆序对 题目描述 给定 n,k ,请求出长度为 n的逆序对数恰好为 k 的排列的个数.答案对 109+7 取模. 对于一个长度为 n 的排列 p ...

随机推荐

  1. 教程|要想Hadoop能够运行Python程序,就要会MRJob

    首先 要想Hadoop能够很流畅的Python程序,学习mrjob可能是最直接.最简单的方法了 你甚至都不要按安装部署Hadoop集群. mrjob拥有很多优秀的特性比如: 支持多步骤的MapRedu ...

  2. Linux shell 整数运算 let [ ] (( )) expr以及 浮点数 bc用法(转)

    Abstract : 1)  Linux shell 中使用 let , [ ] ,(( )) 三种运算符操作 shell 变量进行简单的基本运算:2)Linux shell 中使用 expr 与 b ...

  3. const char and static const char

    部分内容摘自:https://blog.csdn.net/ranhui_xia/article/details/32696669 The version with const char * will ...

  4. kvm-1

    yum install libvirt* virt-* qemu-kvm* -y systemctl start libvirtd.service systemctl status libvirtd. ...

  5. Mybatis实例教程整体说明

    什么是mybatisMyBatis是支持普通SQL查询,存储过程和高级映射的优秀持久层框架.MyBatis消除了几乎所有的JDBC代码和参数的手工设置以及结果集的检索.MyBatis使用简单的XML或 ...

  6. PhpStorm 配置IDE

    IDE => Xdebug => Apache(XAMPP) => Firefox + easist Xdebug 1>XAMPP停止apache服务;2>在安装目录下找 ...

  7. 解决ecplise安装mybatipse插件时报找不到jar包的错

    在安装mybatipse插件的时候一直报这个错,脑袋疼,在网上搜了半天也没有结果,最后摸索了半天解决了,这里先贴一张图 1.先找到eclipse的安装目录,然后把相应的jar包拷到plugins里去, ...

  8. Mybatis学习系列(一)入门简介

    MyBatis简介 Mybatis是Apache的一个Java开源项目,是一个支持动态Sql语句的持久层框架.Mybatis可以将Sql语句配置在XML文件中,避免将Sql语句硬编码在Java类中.与 ...

  9. PAT 1020 月饼

    https://pintia.cn/problem-sets/994805260223102976/problems/994805301562163200 月饼是中国人在中秋佳节时吃的一种传统食品,不 ...

  10. PAT 1030 完美数列

    https://pintia.cn/problem-sets/994805260223102976/problems/994805291311284224 给定一个正整数数列,和正整数 p,设这个数列 ...