不强制在线的动态快速排序 题解


算法一

按照题意模拟

维护一个数组,每次直接往数组后面依次添加\([l, r]\)

每次查询时,暴力地\(sort\)查询即可

复杂度\(O(10^9 * q)\),期望得分\(0\)分

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std; int n, opt;
int q[.........], to; int main() {
cin >> n;
for(int i = 1; i <= n; i ++) {
cin >> opt;
if(opt == 1) {
int l, r;
cin >> l >> r;
for(int j = l; j <= r; j ++) q[++ to] = j;
sort(q + 1, q + to + 1);
to = unique(q + 1, q + to + 1) - q - 1;
}
else {
long long ans = 0;
for(int i = 2; i <= to; i ++)
ans ^= (1ll * q[i] * q[i] - 1ll * q[i - 1] * q[i - 1]);
printf("%lld\n", ans);
}
}
return 0;
}

算法二

\(\bigoplus \limits_{i = 2}^n (a_i^2 - a_{i - 1}^2) = \bigoplus \limits_{i = 2}^n (a_i + a_{i - 1})(a_i - a_{i - 1})\)

当\(a_i = a_{i - 1}\)时,可以发现\((a_i, a_{i - 1})\)是对\(V(S)\)没有贡献的,也就是说,重复的数等价于一个

那么,我们不用数组了

我们用自带去重的\(set\)来模拟插入

查询时暴力即可

期望得分\(0\)分


算法三

插入单点看起来很可做

用一个\(set\)来维护

每次插入时,对前驱后继来讨论即可

插入复杂度\(O(\log n)\),询问复杂度\(O(1)\)

期望得分\(0 \sim 20\)分


算法四

插入的是一段值域区间

因此不妨以区间为单位来考虑

区间\([l, r]\)形成的贡献为\(\bigoplus \limits_{i = 2}^n (a_i - a_{i - 1})* (a_i + a_{i - 1})\),由于\(a_i = a_{i - 1} + 1\)

因此,区间\([l, r]\)形成的贡献为\(\bigoplus \limits_{i = 1}^{n - 1} 2 a_i + 1 = \bigoplus \limits_{i = l}^{r -1} 2i + 1 = \bigoplus \limits_{i = 1}^{r - 1} 2i + 1 \oplus \bigoplus \limits_{i = 1}^{l - 1} 2i + 1\)


考虑怎么求\(\bigoplus \limits_{i = 1}^n 2i + 1\)

  • 这个问题等价于问\([1, 2n + 1]\)中的所有奇数的异或和

    按位分解之后,只要支持区间\([1, n]\)中有多少个\(2^i\)即可

    再来个大力数位\(dp\)

    复杂度\(O(\log^2 n)\)

  • 询问区间\([1, n]\)中有多少个\(2^i\)可以\(O(1)\)回答

    对于每一段\(2^{i + 1}\)而言,前\(2^i\)的第\(i\)位为\(0\),后\(2^i\)的第\(i\)位为\(1\)

    复杂度\(O(\log n)\)

  • 打表,可以发现\(O(1)\)的规律

    设\(n = 4m + k\)

    当\(k = \{0, 1, 2, 3\}\)时,前缀异或和依次为\(2n, 3, 2n + 2, 1\)

    可以考虑用归纳法证明

    复杂度\(O(1)\)

在下文中,我们取\(f(n)\)表示计算异或前缀和的复杂度


可以考虑每次暴力的维护区间的并(用\(sort\)来维护...)

期望得分\(30 \sim 40\)分


算法五

考虑用\(set\)来维护区间

像珂朵莉树那样去维护大概就行了

复杂度\(O(n \log n + n * f(n))\)

期望得分\(50 \sim 100\)分


算法六

考虑用值域线段树来维护

在线段树上的每个节点维护\(min, max, sum\)即可更新

需要动态开点

每次插入对应着给一些区间打标记

每次查询可以直接取\(sum[root]\)即可

注意一个区间被打了标记之后,它的所有子区间都不需要打标记了

复杂度\(O(n f(n) \log 10^9)\)

期望得分\(50 \sim 100\)分

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std; #define ll long long
#define ri register int
#define rep(io, st, ed) for(ri io = st; io <= ed; io ++)
#define drep(io, ed, st) for(ri io = ed; io >= st; io --) #define gc getchar
inline int read() {
int p = 0, w = 1; char c = gc();
while(c > '9' || c < '0') { if(c == '-') w = -1; c = gc(); }
while(c >= '0' && c <= '9') p = p * 10 + c - '0', c = gc();
return p * w;
} const int sid = 1e7 + 5; ll sum[sid];
bool tag[sid];
int m, rt, id;
int mi[sid], mx[sid], ls[sid], rs[sid]; inline void upd(int o) {
int lc = ls[o], rc = rs[o];
mi[o] = mi[lc] ? mi[lc] : mi[rc];
mx[o] = mx[rc] ? mx[rc] : mx[lc];
sum[o] = sum[lc] ^ sum[rc];
if(mx[lc] && mi[rc]) sum[o] ^= 1ll * (mi[rc] + mx[lc]) * (mi[rc] - mx[lc]);
if(tag[lc] && tag[rc]) tag[o] = 1;
} inline int pre(int x) {
int o = x & 3;
if(o == 0) return (x << 1);
if(o == 1) return 3;
if(o == 2) return (x << 1) + 2;
if(o == 3) return 1;
} void mdf(int &o, int l, int r, int ml, int mr) {
if(ml > r || mr < l || tag[o]) return;
if(!o) o = ++ id;
if(ml <= l && mr >= r) {
mi[o] = l; mx[o] = r;
sum[o] = pre(r - 1) ^ pre(l - 1);
tag[o] = 1;
return;
}
int mid = (l + r) >> 1;
mdf(ls[o], l, mid, ml, mr);
mdf(rs[o], mid + 1, r, ml, mr);
upd(o);
} int main() { m = read();
rep(i, 1, m) {
int opt = read();
if(opt == 1) {
int l = read(), r = read();
mdf(rt, 1, 1e9, l, r);
}
else if(opt == 2)
printf("%lld\n", sum[1]);
} return 0;
}

这是一道我也不知道区分了什么反正挺水的题

好像忘了给不会算区间异或和的分了

不管了,反正大家都能A嘛


一些诡异的东西

\(\oplus 2i + 1\),其实等价于\((\oplus i) * 2 + (i \;\&\;1)\)

然后只要考虑\((\oplus i)\)即可

这个就好考虑多了

luoguP5105 不强制在线的动态快速排序 [官方?]题解 线段树 / set的更多相关文章

  1. luoguP5105 不强制在线的动态快速排序

    emm 可重集合没用用.直接变成不可重复集合 有若干个区间 每个区间形如[L,R] [L,R]计算的话,就是若干个连续奇数的和.拆位统计1的个数 平衡树维护 加入一个[L,R],把相交的区间合并.之后 ...

  2. 洛谷 P5105 不强制在线的动态快速排序

    P5105 不强制在线的动态快速排序 题目背景 曦月最近学会了快速排序,但是她很快地想到了,如果要动态地排序,那要怎么办呢? 题目描述 为了研究这个问题,曦月提出了一个十分简单的问题 曦月希望维护一个 ...

  3. P5105 不强制在线的动态快速排序

    P5105 不强制在线的动态快速排序 $\bigoplus \limits_{i=2}^n (a_i^2-a_{i-1}^2) = \bigoplus \limits_{i=2}^n (a_i-a_{ ...

  4. [洛谷P5105]不强制在线的动态快速排序

    题目大意:有一个可重集$S$,有两个操作: $1\;l\;r:$表示把$S$变为$S\cup[l,r]$ $2:$表示将$S$从小到大排序,记为$a_1,a_2,\dots,a_n$,然后求出$\bi ...

  5. [Luogu5105]不强制在线的动态快速排序

    首先集合去重不影响答案,然后打表易得连续自然数平方差异或前缀和的规律,于是问题就变为在线维护区间求并同时更新答案,set记录所有区间,每次暴力插入删除即可.由于每个区间至多只会插入删除一次,故均摊复杂 ...

  6. luogu P5105 不强制在线的动态快速排序

    前言 考试的时候居然想错了区间贡献,mdzz 思路 题目看着很方啊,难道要树套树? 但数据范围提醒我们,是nlogn的复杂度 Sort(S)的定义是不是很鬼畜 但我们不动脑子的打表容易发现 连续区间[ ...

  7. 【BZOJ3295】动态逆序对(线段树,树状数组)

    [BZOJ3295]动态逆序对(线段树,树状数组) 题面 Description 对于序列A,它的逆序对数定义为满足iAj的数对(i,j)的个数.给1到n的一个排列,按照某种顺序依次删除m个元素,你的 ...

  8. 指针-动态开点&合并线段树

    一个知识点不在一道题里说是没有灵魂的 线段树是用来处理区间信息的咯 但是往往因为需要4倍空间让许多人退却,而动态开点的线段树就非常棒 仿佛只用2倍就可以咯 指针保存位置,即节点信息,是很舒适的,所以用 ...

  9. BZOJ 4636 (动态开节点)线段树

    思路: 偷懒 懒得离散化 搞了个动态开节点的线段树 (其实是一样的--..) 注意会有a=b的情况 要判掉 //By SiriusRen #include <cstdio> #includ ...

随机推荐

  1. Python概念-反射之文化底蕴版:反正射了

    什么是反射 光在两种物质分界面上改变传播方向又返回原来物质中的现象,叫反射! 以上,是反射的物理定义,与python中的反射概念,完全没有任何关系 书归正传:反射 就是通过字符串的形式,操作对象相关的 ...

  2. centos7.2安装php7.2

    Centos 7源码编译安装 php7.2 原文地址:https://renwole.com/archives/29 介绍: 先安装php依赖包,否则在编译安装php7的过程当中会出现各种报错,安装完 ...

  3. CodeForces 724G: Xor-matic Number of the Graph

    题目传送门:CF724G. 题意简述: 一张 \(n\) 个点的无向图,边有边权. 定义三元组 \((u,v,w)(1\le u < v\le n)\) 合法当且仅当存在从点 \(u\) 到点 ...

  4. MsSqlserver 查看锁表与解锁

    查看被锁表: select request_session_id spid,OBJECT_NAME(resource_associated_entity_id) tableName from sys. ...

  5. python网络编程-optparse

    Python 有两个内建的模块用于处理命令行参数: 一个是 getopt,<Deep in python>一书中也有提到,只能简单处理 命令行参数: 另一个是 optparse,它功能强大 ...

  6. git —— 远程仓库(创建)

    一.SSH设置 1.创建SSH Key 在用户主目录下,看看有没有.ssh目录, 如果有,再看看这个目录下 有没有id_rsa和id_rsa.pub这两个文件, 如果已经有了,可直接 跳到下一步. 如 ...

  7. 洛谷P1195口袋的天空

    传送门啦 一个裸的最小生成树,输出 $ No Answer $ 的情况只有 $ k < n $ 的时候. 开始令 $ num =n $ ,如果 $ num = k $ ,直接输出 $ 0 $ , ...

  8. 【转】Python验证码识别处理实例

    原文出处: 林炳文(@林炳文Evankaka) 一.准备工作与代码实例 1.PIL.pytesser.tesseract (1)安装PIL:下载地址:http://www.pythonware.com ...

  9. 有关c语言编程

    有关C语言编程 统计代码"行数" 对于统计代码"行数",行数不包括空白行和注释行.程序改进如下: while(fgets (mystring , 100 , f ...

  10. PHP5.6中php-fpm的配置、启动、关闭和重启

    转:http://blog.csdn.net/field_yang/article/details/52401994 该文主要讲述:如何配置PHP-fpm.常见报错解决方法和php-fpm的启动.关闭 ...