写的简单。主要是留给自己做复习资料。


「BZOJ1901」Dynamic Rankings.

给定一个含有 \(n\) 个数的序列 \(a_1,a_2 \dots a_n\),需要支持两种操作:

  • Q l r k 表示查询下标在区间 \([l,r]\) 中的第 \(k\) 小的数。
  • C x y 表示将 \(a_x\) 改为 \(y\)。

引入整体二分。

其实就是我们对于二分到的一个值域 mid,去离线针对所有的询问进行 check。

具体是利用一些数据结构。

然后根据 check 和 mid 的大小将询问分为两拨,再分治下去解决问题。

参考于 OI-wiki 的板子很精简且思路便于理解。

#include <cstdio>

int Abs (int x) { return x < 0 ? -x : x; }
int Max (int x, int y) { return x > y ? x : y; }
int Min (int x, int y) { return x < y ? x : y; } int Read () {
int x = 0, k = 1;
char s = getchar();
while (s < '0' || s > '9') {
if(s == '-')
k = -1;
s = getchar ();
}
while ('0' <= s && s <= '9')
x = (x << 3) + (x << 1) + (s ^ 48), s = getchar ();
return x * k;
} void Write (int x) {
if(x < 0)
x = -x, putchar ('-');
if(x > 9)
Write (x / 10);
putchar (x % 10 + '0');
} void Print (int x, char s) { Write (x), putchar (s); } const int MAXN = 2e5 + 5; char Opt[3];
int Ans[MAXN], BIT[MAXN], a[MAXN], n, m; int Low_Bit (int x) {
return x & -x;
} void Update (int k, int x) {
for (int i = k; i <= n; i += Low_Bit (i))
BIT[i] += x;
} int Query (int k) {
int Res = 0;
for (int i = k; i >= 1; i -= Low_Bit (i))
Res += BIT[i];
return Res;
} struct Node {
bool Type;
int Id, x, y, k;
Node () {}
Node (bool T, int I, int X, int Y, int K) {
Type = T, Id = I, x = X, y = Y, k = K;
}
} q[MAXN], Tmp[2][MAXN]; void Solve (int l, int r, int L, int R) {
if (l > r || L > R)
return ;
if (L == R) {
for (int i = l; i <= r; i++)
if (q[i].Type)
Ans[q[i].Id] = L;
return ;
}
int Mid = (L + R) >> 1, Cnt0 = 0, Cnt1 = 0;
for (int i = l; i <= r; i++)
if (q[i].Type) {
int Check = Query (q[i].y) - Query (q[i].x - 1);
if (q[i].k <= Check)
Tmp[0][++Cnt0] = q[i];
else
q[i].k -= Check, Tmp[1][++Cnt1] = q[i];
}
else {
if (q[i].y <= Mid)
Update (q[i].x, q[i].k), Tmp[0][++Cnt0] = q[i];
else
Tmp[1][++Cnt1] = q[i];
}
for (int i = 1; i <= Cnt0; i++)
if (!Tmp[0][i].Type)
Update (Tmp[0][i].x, -Tmp[0][i].k);
for (int i = 1; i <= Cnt0; i++)
q[l + i - 1] = Tmp[0][i];
for (int i = 1; i <= Cnt1; i++)
q[l + Cnt0 + i - 1] = Tmp[1][i];
Solve (l, l + Cnt0 - 1, L, Mid), Solve (l + Cnt0, r, Mid + 1, R);
} int main () {
n = Read (), m = Read ();
int p = 0, Tot = 0;
for (int i = 1, x; i <= n; i++)
x = Read (), q[++p] = Node (0, 0, i, x, 1), a[i] = x;
for (int i = 1, x, y; i <= m; i++) {
scanf ("%s", Opt + 1), x = Read (), y = Read ();
if (Opt[1] == 'Q') {
int k = Read ();
q[++p] = Node (1, ++Tot, x, y, k);
}
else
q[++p] = Node (0, 0, x, a[x], -1), q[++p] = Node (0, 0, x, y, 1), a[x] = y;
}
Solve (1, p, 0, 1e9);
for (int i = 1; i <= Tot; i++)
Print (Ans[i], '\n');
return 0;
}

「ZJOI2013」K 大数查询

需要维护 \(n\) 个可重整数集,集合的编号从 \(1\) 到 \(n\)。这些集合初始都是空集,有 \(m\) 个操作:

  • 1 l r c 表示将 \(c\) 加入到编号在 \([l,r]\) 内的集合中。
  • 2 l r c 表示查询编号在 \([l,r]\) 内的集合的并集中,第 \(c\) 大的数是多少。

注意可重集的并是不去除重复元素的,如 \(\{1,1,4\}\cup\{5,1,4\}=\{1,1,4,5,1,4\}\)。

放在这里是因为发现它比上道题的唯一差别在于区间修改。

也就是说整体二分的数据结构理论上可以百搭。比如线段树。

#include <cstdio>

typedef long long LL;
int Abs (int x) { return x < 0 ? -x : x; }
int Max (int x, int y) { return x > y ? x : y; }
int Min (int x, int y) { return x < y ? x : y; } int Read () {
int x = 0, k = 1;
char s = getchar();
while (s < '0' || s > '9') {
if(s == '-')
k = -1;
s = getchar ();
}
while ('0' <= s && s <= '9')
x = (x << 3) + (x << 1) + (s ^ 48), s = getchar ();
return x * k;
} LL Read_LL () {
LL x = 0, k = 1;
char s = getchar();
while (s < '0' || s > '9') {
if(s == '-')
k = -1;
s = getchar ();
}
while ('0' <= s && s <= '9')
x = (x << 3) + (x << 1) + (s ^ 48), s = getchar ();
return x * k;
} void Write (int x) {
if(x < 0)
x = -x, putchar ('-');
if(x > 9)
Write (x / 10);
putchar (x % 10 + '0');
} void Print (int x, char s) { Write (x), putchar (s); } const int MAXN = 5e4 + 5; int Ans[MAXN], n, m; struct Segment_Tree {
#define Lson p << 1
#define Rson p << 1 | 1 struct Segment_Node {
int l, r;
bool Clear;
LL Sum, Lazy;
Segment_Node () {}
Segment_Node (int L, int R, LL S, LL La, bool C) {
l = L, r = R, Sum = S, Lazy = La, Clear = C;
}
} Tr[MAXN * 4]; void Push (int p) {
if (Tr[p].Clear) {
Tr[Lson].Sum = Tr[Rson].Sum = 0;
Tr[Lson].Lazy = Tr[Rson].Lazy = 0;
Tr[Lson].Clear = Tr[Rson].Clear = true;
Tr[p].Clear = false;
}
if (Tr[p].Lazy) {
Tr[Lson].Sum += Tr[p].Lazy * (Tr[Lson].r - Tr[Lson].l + 1);
Tr[Rson].Sum += Tr[p].Lazy * (Tr[Rson].r - Tr[Rson].l + 1);
Tr[Lson].Lazy += Tr[p].Lazy, Tr[Rson].Lazy += Tr[p].Lazy;
Tr[p].Lazy = 0;
}
} void Pull (int p) {
Tr[p].Sum = Tr[Lson].Sum + Tr[Rson].Sum;
} void Make_Tree (int p, int l, int r) {
Tr[p].l = l, Tr[p].r = r;
if (Tr[p].l == Tr[p].r)
return ;
int Mid = (Tr[p].l + Tr[p].r) >> 1;
Make_Tree (Lson, l, Mid);
Make_Tree (Rson, Mid + 1, r);
} void Update (int p, int l, int r, LL x) {
if (l <= Tr[p].l && Tr[p].r <= r) {
Tr[p].Sum += x * (Tr[p].r - Tr[p].l + 1), Tr[p].Lazy += x;
return ;
}
Push (p);
int Mid = (Tr[p].l + Tr[p].r) >> 1;
if (l <= Mid)
Update (Lson, l, r, x);
if (r > Mid)
Update (Rson, l, r, x);
Pull (p);
} LL Query (int p, int l, int r) {
if (l <= Tr[p].l && Tr[p].r <= r)
return Tr[p].Sum;
Push (p);
int Mid = (Tr[p].l + Tr[p].r) >> 1;
LL Res = 0;
if (l <= Mid)
Res += Query (Lson, l, r);
if (r > Mid)
Res += Query (Rson, l, r);
Pull (p);
return Res;
} #undef Lson
#undef Rson
} Seg; struct Node {
LL k;
bool Type;
int Id, x, y;
Node () {}
Node (bool T, int I, int X, int Y, LL K) {
Type = T, Id = I, x = X, y = Y, k = K;
}
} q[MAXN], Tmp[2][MAXN]; void Solve (int l, int r, int L, int R) {
if (l > r || L > R)
return ;
if (L == R) {
for (int i = l; i <= r; i++)
if (q[i].Type)
Ans[q[i].Id] = L;
return ;
}
int Mid = (L + R) >> 1, Cnt0 = 0, Cnt1 = 0;
Seg.Tr[1].Clear = true, Seg.Tr[1].Sum = Seg.Tr[1].Lazy = 0;
for (int i = l; i <= r; i++)
if (q[i].Type) {
LL Check = Seg.Query(1, q[i].x, q[i].y);
if (q[i].k <= Check)
Tmp[1][++Cnt1] = q[i];
else
q[i].k -= Check, Tmp[0][++Cnt0] = q[i];
}
else {
if (q[i].k > Mid)
Seg.Update (1, q[i].x, q[i].y, 1ll), Tmp[1][++Cnt1] = q[i];
else
Tmp[0][++Cnt0] = q[i];
}
for (int i = 1; i <= Cnt0; i++)
q[l + i - 1] = Tmp[0][i];
for (int i = 1; i <= Cnt1; i++)
q[l + Cnt0 + i - 1] = Tmp[1][i];
Solve (l, l + Cnt0 - 1, L, Mid), Solve (l + Cnt0, r, Mid + 1, R);
} int main () {
LL k;
n = Read (), m = Read ();
int p = 0, Tot = 0;
Seg.Make_Tree (1, 1, n);
for (int i = 1, Opt, x, y; i <= m; i++) {
Opt = Read (), x = Read (), y = Read (), k = Read_LL ();
if (Opt == 1)
q[++p] = Node (0, i, x, y, k);
else
q[++p] = Node (1, ++Tot, x, y, k);
}
Solve (1, p, -n, n);
for (int i = 1; i <= Tot; i++)
Print (Ans[i], '\n');
return 0;
}

Template -「整体二分」的更多相关文章

  1. 「CF484E」Sign on Fence「整体二分」「线段树」

    题意 给定一个长度为\(n\)的正整数序列,第\(i\)个数为\(h_i\),\(m\)个询问,每次询问\((l, r, w)\),为\([l, r]\)所有长度为\(w\)的子区间最小值的最大值.( ...

  2. Template -「网络流 & 二分图」

    EK. 很少用到,知道思想即可. 懒得写封装的屑. queue<int> q; int Cap[MAXN][MAXN], Flow[MAXN][MAXN], Aug[MAXN], fa[M ...

  3. Template -「矩阵 - 行列式」

    #include <cstdio> int Abs(int x) { return x < 0 ? -x : x; } int Max(int x, int y) { return ...

  4. loj #535. 「LibreOJ Round #6」花火 树状数组求逆序对+主席树二维数点+整体二分

    $ \color{#0066ff}{ 题目描述 }$ 「Hanabi, hanabi--」 一听说祭典上没有烟火,Karen 一脸沮丧. 「有的哦-- 虽然比不上大型烟花就是了.」 还好 Shinob ...

  5. loj3161「NOI2019」I 君的探险(随机化,整体二分)

    loj3161「NOI2019」I 君的探险(随机化,整体二分) loj Luogu 题解时间 对于 $ N \le 500 $ 的点,毫无疑问可以直接 $ O(n^2) $ 暴力询问解决. 考虑看起 ...

  6. 【LOJ2402】「THUPC 2017」天天爱射击 / Shooting(整体二分)

    点此看题面 大致题意: 有\(n\)个区间,每个区间有一个权值,当权值变成\(0\)时消失.每个时刻将覆盖某一位置的所有区间权值减\(1\),求每个时刻有多少个区间在这一刻消失. 前言 整体二分裸题啊 ...

  7. 【BZOJ4009_洛谷3242】[HNOI2015] 接水果(整体二分)

    题目: 洛谷 3242 分析: 明确题意:在一棵树上给定若干权值为 \(w\) 的路径 \((u,v)\) (盘子),每次给定 \((a,b)\) (水果),询问所有满足 \((u,v)\) 被 \( ...

  8. 「DP 浅析」斜率优化

    #0.0 屑在前面 将结合经典例题 「HNOI2008」玩具装箱 以及 「NOI2007」货币兑换 进行讲解. #1.0 简述 #1.1 适用情况 斜率优化一般适用于状态转移方程如下的 DP \[f_ ...

  9. 「TJOI / HEOI2016」字符串

    「TJOI / HEOI2016」字符串 题目描述 佳媛姐姐过生日的时候,她的小伙伴从某东上买了一个生日礼物.生日礼物放在一个神奇的箱子中.箱子外边写了一个长为 \(n\) 的字符串 \(s\),和 ...

随机推荐

  1. MySQL性能优化 - 别再只会说加索引了

    MySQL性能优化 MySQL性能优化我们可以从以下四个维度考虑:硬件升级.系统配置.表结构设计.SQL语句和索引. 从成本上来说:硬件升级>系统配置>表结构设计>SQL语句及索引, ...

  2. Linux 环境变量配置的 6 种方法,建议收藏

    关注「开源Linux」,选择"设为星标" 回复「学习」,有我为您特别筛选的学习资料~ Linux环境变量配置 在自定义安装软件的时候,经常需要配置环境变量,下面列举出各种对环境变量 ...

  3. 关于数据拓展及面试题讲解 Java

    强类型语言  要求变量的使用严格符合规定,所有变量都必须先定义后才能使用 弱类型语言 Java 的数控类型分为两大类 基本类型(primitive type) 引用类型(reference type) ...

  4. IIS发布Https和Https的问题

    asp.net调试页面的时候遇到一个问题,我喜欢右键点击在浏览器查看页面,打开的页面默认是https的,其实iis会同时生成http和https两种页面,但是我懒得每次去点.问题是页面中测试接口是ht ...

  5. 移动端input的disabled属性对字体颜色影响

    对于表单输入,input是很好的选择,这次记录主要是正对input的value值字体在Android和iOS(11)设备下显示不同问题: 如下图:1.2的区别主要是分别设置disabled.reado ...

  6. Spring Boot 2.7.0发布,2.5停止维护,节奏太快了吧

    这几天是Spring版本日,很多Spring工件都发布了新版本, Spring Framework 6.0.0 发布了第 4 个里程碑版本,此版本包含所有针对 5.3.20 的修复补丁,以及特定于 6 ...

  7. unity---角色控制器控制角色移动

    获取对象 public CharacterController cc; cc=gameObject.GetComponent<CharacterController>(); if(Inpu ...

  8. 130_传析阅管理系统accdb64位版本

    博客:www.jiaopengzi.com 焦棚子的文章目录 请点击下载附件 几年前笔者针对家居门店的进销存.人员管理.工资管理.任务系统.门店经营盈亏管理.销售分析.考勤请假等息息相关的业务基于Ac ...

  9. 【Axure】母版引发事件

    引发事件是指你将母版中某一元件的事件从母版中提升出来,以使其在页面的级别可用. 通过引发事件,可以对在不同页面上母版实例的同一个元件设置不同的交互. 设置引发事件 打开一个母版: 选择其中一个组件: ...

  10. HTML5续集

    H5 input新增属性 1.color 拾色器 2.Email 电子邮件 3.tel 电话 4.datetime-local 本地日期和时间 5.range 范围 6.url 路径,地址 7.sea ...