传送门: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. Java 图像处理框架-Marvin

    网上看到,摘录过来的,暂时还没涉足这方面的东西 Marvin 1.4.5 的插件接口支持处理多个图像作为输入,新的插件可通过多个图片来确认背景,新的插件可使用多个图片来合并相同场景. Marvin 是 ...

  2. 护网杯 three hit 复现(is_numeric引发的二次注入)

    1.题目源码 https://github.com/ZhangAiQiang/three-hit 题目并不真的是当时源码,是我根据做法自己写的,虽然代码烂,但是还好能达到复现的目的 ,兄弟们star一 ...

  3. Eureka搭建

    Eureka搭建 一.Eureka基本框架搭建 pom.xml文件配置:主要是引入Eureka所依赖的jar包 <?xml version="1.0" encoding=&q ...

  4. 学习bash——通配符与特殊符号

    一.通配符 这是bash操作环境中一个非常有用的功能,这让我们使用bash处理数据就更方便了. 常用通配符如下: 符号 意义 * 代表0个到无穷多个任意字符 ? 代表一个任意字符 [] 代表一定有一个 ...

  5. 使用ValueOperations操作redis

    方法 c参数 s说明   void set(K key, V value); key :字段key value:key对应的值  设置一个key和value   void set(K key, V v ...

  6. oracle INSERT INTO多个值

    稍微熟悉Oracle的都知道,如果我们想一条SQL语句向表中插入多个值的话,如果INSERT INTO 某表 VALUES(各个值),VALUES(各个值),.....;这样会报错的,因为oracle ...

  7. android命令模式IntentService 远程下载文件

    服务可用在一下情景: 1,用户离开activity后,仍需要继续工作,例如从网络下载文件,播放音乐. 2,无论activity出现或离开,都需要持续工作,例如网络聊天应用. 3,连接网络服务,正在使用 ...

  8. lintcode-118-不同的子序列

    118-不同的子序列 给出字符串S和字符串T,计算S的不同的子序列中T出现的个数. 子序列字符串是原始字符串通过删除一些(或零个)产生的一个新的字符串,并且对剩下的字符的相对位置没有影响.(比如,&q ...

  9. 浅拷贝&深拷贝&Copy On Write(Sring类)

    String类的三种实现 浅拷贝 class String { public: String(const char* pdata)//构造函数 :_pdata(]) { strcpy(_pdata, ...

  10. NotifyIcon控件

    NotifyIcon就是系统托盘控件.通知区域中的图标是一些进程的快捷方式,这些进程在计算机后台运行,如防病毒程序或音量控制.这些进程不会具有自己的用户界面.NotifyIcon 类提供了编写此功能的 ...