传送门: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. python os模块atime ,ctime,mtime意义

    ython的os.stat中主要的时间信息有三个:st_mtime,st_atime,st_ctime.   1.st_mtime:time of last modification      最后一 ...

  2. Extjs报错:isField为空或不是对象

             在做Extjs开发的时候,有时候会碰到一个奇怪的问题,就是报错说"isField为空或不是对象",经过调试发现是一个数组,显示的长度是21,但是数组里面的个数只有 ...

  3. 「题目代码」P1007~P1012(Java)

    1007 C基础-计负均正 import java.util.*; import java.io.*; public class Main { public static void main(Stri ...

  4. Linux-Shell脚本编程-学习-6-Shell编程-使用结构化命令-文件比较-case编程

    这一片主要说test文件的比较,文件比较在日常使用的频率比较高,这里重点把每个部分都试着说说看 1. 检车目录 -d -d测试会检查指定的文件名是否在系统上以目录的形式存在,当我们要写文件到某个目录之 ...

  5. python学习总结----简单数据结构

    mini-web服务器 - 能够完成简单的请求处理 - 使用http协议 - 目的:加深对网络编程的认识.为后面阶段学习web做铺垫 简单数据结构 - 排列组合 import itertools # ...

  6. BZOJ 1923 SDOI2010 外星千足虫 异或方程组+bitset

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1923 懒得贴题目了......这就是解一个异或方程组的裸题...... YY了一下异或方程 ...

  7. NO5——素数筛选

    #include <stdio.h> int main() { ]={}; ;i<=;i++) a[i]=; ;i<=;i++) if(a[i]) ;j+=i) a[j]=; ...

  8. STL中list的erase()方法

    http://www.cnblogs.com/gshlsh17/ rase()方法是删除iterator指定的节点  但是要注意的是在执行完此函数的时候iterator也被销毁了   这样的话关于it ...

  9. Football Games(思维题)

    Problem Description A mysterious country will hold a football world championships---Abnormal Cup, at ...

  10. Redis数据类型及操作详解

    Redis数据库,是nosql的一种.与传统关系型数据库(如mysql.sqlserver等)相比,他在处理大数据量上相当有优势,扩展性和可用性高,这是传统型数据库所达不到的. Redis是一个key ...