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


算法一

按照题意模拟

维护一个数组,每次直接往数组后面依次添加\([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. 【JSON】Ajax获得JSON字符串的处理方法

    一. success : function(data){ var caseInfoView = eval('('+data.caseInfoView+')'); for(var key in case ...

  2. TcxScheduler的使用

    TcxScheduler有两种工作模式: 一.非绑定模式 非绑定模式下,数据被存储在文件系统中.要让scheduler工作在非绑定模式下,应使TcxScheduler.Storage属性绑定到TcxS ...

  3. 高性能.NET MVC之QMVC!

    ASP.NET!这个词代表者一个单词Fat!因为他总是捆绑着太多的太多的类,太多太多的各种功能!你也许会用到,如果你反编译或阅读他们开源的源码,你会不会犹如在大海中找不到方向?不管是Web form ...

  4. 使用离线包部署kubernetes 1.9.0、kubernetes-dashboard 1.8

    =============================================== 2018/3/22_第2次修改                       ccb_warlock 更新 ...

  5. 10 The Go Programming Language Specification go语言规范 重点

    The Go Programming Language Specification go语言规范 Version of May 9, 2018 Introduction 介绍 Notation 符号 ...

  6. nvm npm node.js的关系

    nvm   npm  node.js都是用来构建reactNativ的项目 nvm管理node.j和npm版本的 node.js管理reactNative开发中所需要的代码库的 npm管理对应node ...

  7. 在VS中让一个JS文件智能提示另一个JS文件中的成员2--具体引用

    我们知道,在html中,利用<script language="javascript" type="text/javascript" src=" ...

  8. linux定时任务-cron

    /sbin/service crond start //启动服务 /sbin/service crond stop //关闭服务 /sbin/service crond restart //重启服务 ...

  9. 洛谷P3811乘法逆元

    传送门 线性递推 #include <iostream> #include <cstdio> #include <cstring> #include <alg ...

  10. 洛谷P1525关押罪犯

    传送门啦 想让最大值最小,所以,这题可以用二分法,排序之后发现可以并查集,因为要使最大值最小,排序后这个最大值是存在的. 对于会冲突的两个罪犯,我们连一条无向边,然后按权值从大到小排序,从大到小枚举每 ...