考虑分块,每个块都是用 链表 维护的,并保证 \(size\) 和分块相当。

我们考虑一下怎么去查询,很显然,可以对值域分块,单点修改,记录前缀和,完全ojbk了,对每个块维护一个 \(pre , prb\) 数组

\(pre_{i,j}\) 数组表示 \(1~i\) 这些块中,出现了多少个 \(j\)

\(prb_{i,j}\) 数组表示 \(1~i\) 这些块中,在值域块 \(j\) 的有多少个

零散部分查一查就好了,修改也是稳定 \(\sqrt n\) 的,插入也是。

// powered by c++11
// by Isaunoya
#pragma GCC optimize("Ofast")
#pragma GCC optimize("unroll-loops")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#include <bits/stdc++.h>
#define rep(i, x, y) for (register int i = (x); i <= (y); ++i)
#define Rep(i, x, y) for (register int i = (x); i >= (y); --i)
using namespace std;
using db = double;
using ll = long long;
using uint = unsigned int;
using pii = pair<int, int>;
#define ve vector
#define Tp template
#define all(v) v.begin(), v.end()
#define sz(v) ((int)v.size())
#define pb emplace_back
#define fir first
#define sec second
// the cmin && cmax
Tp<class T> void cmax(T& x, const T& y) {
if (x < y) x = y;
}
Tp<class T> void cmin(T& x, const T& y) {
if (x > y) x = y;
}
// sort , unique , reverse
Tp<class T> void sort(ve<T>& v) { sort(all(v)); }
Tp<class T> void unique(ve<T>& v) {
sort(all(v));
v.erase(unique(all(v)), v.end());
}
Tp<class T> void reverse(ve<T>& v) { reverse(all(v)); }
const int SZ = 0x191981;
struct FILEIN {
char qwq[SZ], *S = qwq, *T = qwq, ch;
char GETC() { return (S == T) && (T = (S = qwq) + fread(qwq, 1, SZ, stdin), S == T) ? EOF : *S++; }
FILEIN& operator>>(char& c) {
while (isspace(c = GETC()))
;
return *this;
}
FILEIN& operator>>(string& s) {
while (isspace(ch = GETC()))
;
s = ch;
while (!isspace(ch = GETC())) s += ch;
return *this;
}
Tp<class T> void read(T& x) {
bool sign = 1;
while ((ch = GETC()) < 0x30)
if (ch == 0x2d) sign = 0;
x = (ch ^ 0x30);
while ((ch = GETC()) > 0x2f) x = x * 0xa + (ch ^ 0x30);
x = sign ? x : -x;
}
FILEIN& operator>>(int& x) { return read(x), *this; }
FILEIN& operator>>(unsigned& x) { return read(x), *this; }
} in;
struct FILEOUT {
const static int LIMIT = 0x114514;
char quq[SZ], ST[0x114];
signed sz, O;
~FILEOUT() { flush(); }
void flush() {
fwrite(quq, 1, O, stdout);
fflush(stdout);
O = 0;
}
FILEOUT& operator<<(char c) { return quq[O++] = c, *this; }
FILEOUT& operator<<(string str) {
if (O > LIMIT) flush();
for (char c : str) quq[O++] = c;
return *this;
}
Tp<class T> void write(T x) {
if (O > LIMIT) flush();
if (x < 0) {
quq[O++] = 0x2d;
x = -x;
}
do {
ST[++sz] = x % 0xa ^ 0x30;
x /= 0xa;
} while (x);
while (sz) quq[O++] = ST[sz--];
return;
}
FILEOUT& operator<<(int x) { return write(x), *this; }
FILEOUT& operator<<(unsigned x) { return write(x), *this; }
} out;
int n, m;
const int maxn = 7e4 + 47;
const int blc = 235;
const int S = 300;
list<int> s[S];
#define bl(x) ((x - 1) / S + 1)
int pre[maxn][S], prb[S][S], L[S], R[S], cnt[maxn], t[S], st[S << 1], top = 0, ans = 0;
inline int modify(list<int>& l, int x, int v) {
auto it = l.begin();
while (x--) ++it;
int res = *(it);
return *(it) = v, res;
}
inline void get(list<int>& l, int x, int y) {
auto it = l.begin();
while (x--) ++it;
while (y--) {
++cnt[st[++top] = *(it)], ++t[bl(*(it))], ++it;
}
}
void qry(int l, int r, int k) {
top = 0;
const int bL = bl(l), bR = bl(r);
if (bL == bR) {
get(s[bL], l - L[bL], r - l + 1);
for (int i = 1;; i++) {
if (k > t[i]) {
k -= t[i];
} else {
for (int j = L[i];; ++j)
if (k > cnt[j]) {
k -= cnt[j];
} else {
ans = j;
break;
}
break;
}
}
} else {
get(s[bL], l - L[bL], R[bL] - l + 1), get(s[bR], 0, r - L[bR] + 1);
for (int i = 1;; i++) {
if (k > t[i] + prb[i][bR - 1] - prb[i][bL]) {
k -= (t[i] + prb[i][bR - 1] - prb[i][bL]);
} else {
for (int j = L[i];; ++j)
if (k > cnt[j] + pre[j][bR - 1] - pre[j][bL]) {
k -= (cnt[j] + pre[j][bR - 1] - pre[j][bL]);
} else {
ans = j;
break;
}
break;
}
}
}
ans--;
for (int i = 0; i <= top; i++) {
t[bl(st[i])] = 0, cnt[st[i]] = 0;
}
}
inline void change(int x, int v) {
const int bel = bl(x);
int las = modify(s[bel], x - L[bel], v);
for (int i = bel; i <= blc; i++) {
--pre[las][i], --prb[bl(las)][i], ++pre[v][i], ++prb[bl(v)][i];
}
}
inline void ins(int x, int v) {
const int bel = bl(x);
auto it = s[bel].begin();
for (int i = x - L[bel]; i--;) ++it;
s[bel].insert(it, v);
for (int i = bel; i <= blc; i++) {
++pre[v][i], ++prb[bl(v)][i];
}
for (int i = bel + 1; i <= blc; i++) {
if (s[i - 1].size() <= S) {
break;
} else {
int las = s[i - 1].back();
--pre[las][i - 1], --prb[bl(las)][i - 1];
s[i - 1].pop_back(), s[i].push_front(las);
}
}
}
signed main() {
#ifdef _WIN64
freopen("testdata.in", "r", stdin);
#else
ios_base ::sync_with_stdio(false);
cin.tie(nullptr), cout.tie(nullptr);
#endif
// code begin.
in >> n;
rep(i, 1, blc) { L[i] = R[i - 1] + 1, R[i] = L[i] + S - 1; }
rep(i, 1, n) {
int x;
const int bel = bl(i);
in >> x, ++x, s[bel].pb(x);
rep(j, bel, blc) { ++pre[x][j], ++prb[bl(x)][j]; }
}
in >> m;
while (m--) {
char c;
in >> c;
if (c == 'Q') {
int l, r, k;
in >> l >> r >> k, qry(l ^ ans, r ^ ans, k ^ ans), out << ans << '\n';
}
if (c == 'M') {
int x, v;
in >> x >> v, x ^= ans, v ^= ans, ++v, change(x, v);
}
if (c == 'I') {
int x, v;
in >> x >> v, x ^= ans, v ^= ans, ++v, ins(x, v);
}
}
return 0;
// code end.
}

「BZOJ3065」带插入区间K小值 [分块]的更多相关文章

  1. 【BZOJ3065】带插入区间K小值 替罪羊树+权值线段树

    [BZOJ3065]带插入区间K小值 Description 从前有n只跳蚤排成一行做早操,每只跳蚤都有自己的一个弹跳力a[i].跳蚤国王看着这些跳蚤国欣欣向荣的情景,感到非常高兴.这时跳蚤国王决定理 ...

  2. 【bzoj3065】带插入区间K小值 替罪羊树套权值线段树

    题目描述 从前有n只跳蚤排成一行做早操,每只跳蚤都有自己的一个弹跳力a[i].跳蚤国王看着这些跳蚤国欣欣向荣的情景,感到非常高兴.这时跳蚤国王决定理性愉悦一下,查询区间k小值.他每次向它的随从伏特提出 ...

  3. 【BZOJ3065】带插入区间k小值

    题意: 带插入,修改的区间k小值在线查询 原序列长度<=35000,插入个数<=35000,修改个数<=70000,0<=权值<=70000 题解: Orz vfleak ...

  4. 【bzoj3065】: 带插入区间K小值 详解——替罪羊套函数式线段树

    不得不说,做过最爽的树套树———— 由于有了区间操作,我们很容易把区间看成一棵平衡树,对他进行插入,那么外面一层就是平衡树了,这就与我们之前所见到的不同了.我们之前所见到的大多数是线段树套平衡树而此题 ...

  5. BZOJ3065:带插入区间K小值

    浅谈树状数组与主席树:https://www.cnblogs.com/AKMer/p/9946944.html 题目传送门:https://www.lydsy.com/JudgeOnline/prob ...

  6. [BZOJ3065]带插入区间K小值 解题报告 替罪羊树+值域线段树

    刚了一天的题终于切掉了,数据结构题的代码真**难调,这是我做过的第一道树套树题,做完后感觉对树套树都有阴影了......下面写一下做题记录. Portal Gun:[BZOJ3065]带插入区间k小值 ...

  7. bzoj 3065: 带插入区间K小值 替罪羊树 && AC300

    3065: 带插入区间K小值 Time Limit: 60 Sec  Memory Limit: 512 MBSubmit: 1062  Solved: 253[Submit][Status] Des ...

  8. 【题解】BZOJ 3065: 带插入区间K小值——替罪羊树套线段树

    题目传送门 题解 orz vfk的题解 3065: 带插入区间K小值 系列题解 一 二 三 四 惨 一开始用了一种空间常数很大的方法,每次重构的时候merge两颗线段树,然后无限RE(其实是MLE). ...

  9. 3065: 带插入区间K小值_树套树_替罪羊树_权值线段树

    经过周六一天,周一3个小时的晚自习,周二2个小时的疯狂debug,终于凭借自己切掉了这道树套树题. Code: #include <cstdio> #include <algorit ...

随机推荐

  1. Ceph 存储集群7-故障排除

    Ceph 仍在积极开发中,所以你可能碰到一些问题,需要评估 Ceph 配置文件.并修改日志和调试选项来纠正它. 一.日志记录和调试 般来说,你应该在运行时增加调试选项来调试问题:也可以把调试选项添加到 ...

  2. 死磕java(1)

    java入门 package com.sougn.new1; public class new1 { /**   * @param args   */  public static void main ...

  3. A Simple Introduction To Computer Networking

    Most networking discussions are a jumble of acronyms. Forget the configuration details - what are th ...

  4. linux笔记之解压

    从1.15版本开始tar就可以自动识别压缩的格式,故不需人为区分压缩格式就能正确解压: Linux下常见的压缩包格式有5种:zip tar.gz tar.bz2 tar.xz tar.Z 其中tar是 ...

  5. POJ_2342_树状dp

    http://poj.org/problem?id=2342 第一道树状dp,入门题,用vector构建有向图. #include<iostream> #include<cstrin ...

  6. HDU_5094_dfs

    http://acm.hdu.edu.cn/showproblem.php?pid=5094 bfs,vis[x][y][z],z表示钥匙的状态,用二进制来表示,key[x][y]储存当前位置钥匙的二 ...

  7. java4选择结构 二

    public class jh_01_为什么使用switch选择结构 { /* * 韩嫣参加计算机编程大赛 * 如果获得第一名,将参加麻省理工大学组织的1个月夏令营 * 如果获得第二名,将奖励惠普笔记 ...

  8. 利用idea对tomcat容器进行debug

    通过idea对tomcat容器进行debug有两种方式: 一种直接修改idea中引用tomcat的启动配置 另一种是修改tomcat的启动脚本再通过设置diea的远程debug的方式进行调试 1.设置 ...

  9. 深入理解JVM(学习过程)

    这,仅是我学习过程中记录的笔记.确定了一个待研究的主题,对这个主题进行全方面的剖析.笔记是用来方便我回顾与学习的,欢迎大家与我进行交流沟通,共同成长.不止是技术. 2020年02月06日22:43:0 ...

  10. VFP CursorAdapter 起步二(作者:Doug Hennig 译者:fbilo)

    用 CursorAdapter 来取得和更新数据 在 VFP8 中新增的 CursorAdapter 基类提供一个统一.易用的数据接口.Doug Hennig 在这个月的文章中演示了怎样使用 Curs ...