ZOJ2112 Dynamic Rankings(整体二分)
今天学习了一个奇技淫巧--整体二分。关于整体二分的一些理论性的东西,可以参见XRH的《浅谈数据结构题的几个非经典解法》。然后下面是一些个人的心得体会吧,写下来希望加深一下自己的理解,或者如果有人看了或许也有些帮助。
ZOJ2112是一道典型的带修改的区间第k大的问题,有一些树套树等的数据结构可以在线处理这样的问题。但是当题目并不要求在线处理的时候,其实我们可以选择一下整体二分的思想。
个人对整体二分的理解是这样子的,首先对于修改,即把a[xi]=yi(1<=yi<=C)的时候,我们可以把修改的操作划分成两部分,一部分是yi<=mid,另一部分是yi>mid。首先我们忽略掉yi>mid的操作,将yi<=mid以及询问操作按照输入的顺序执行一遍,这样我们就可以知道<=mid的操作对所有询问的贡献,接下来我们就要根据贡献对修改操作划分成两部分,一部分是答案在<=mid里面的,另外一部分是答案在>mid里面的,对于<=mid的,显然我们可以递归求解(因为>mid的操作对那些<=mid是没有影响的),而对于>mid的来说,<=mid的操作是有影响的,但是<=mid所造成的影响已经算过一遍了,所以对于>mid的来说,其实也是独立的。所以如果我们把答案二分的范围的大小设为C,操作的总数设为n,那么划分到<=mid的操作是n1,>mid的操作是n2时(n1+n2=n)
有 T(n,C)=T(n1,C/2)+T(n2,C/2)+O(nlogC) T(n)=nlogC^2...(也不知道复杂度对不对,可以画一个图来YY一下)
好吧,其实我也不知道上面说了什么,感觉真的蛮难用一两段话将整个思路说出来的。其实总的抽象的来说,就是一开始维护的可能答案的区间是[l,r],
然后我们将所有<=mid的操作作一遍,然后将答案落在[l,mid]的操作(询问和修改)划到一边,将答案落在[mid+1,r]的操作(询问和修改)划到另一边。
- #pragma warning(disable:4996)
- #include <cstdio>
- #include <cstring>
- #include <iostream>
- #include <algorithm>
- #include <cmath>
- #include <string>
- #include <vector>
- #include <queue>
- using namespace std;
- #define maxn 300000
- struct Query
- {
- int x, y; // qt==3 [x,y] qt==1||2 a[x]=y
- int qt; // query type 1 for increase 2 for decrease 3 for query
- int cur; // the current contribution
- int k; // the query is the k-th smalleset
- int index;
- }q[maxn];
- int qtop;
- int a[maxn];
- int b[maxn];
- int bsize;
- int n, m;
- int tot;
- int ans[maxn];
- int ansid;
- int tmp[maxn];
- Query q1[maxn], q2[maxn];
- int bit[maxn];
- void add(int x, int v)
- {
- while (x <= n){
- bit[x] += v;
- x += x&(-x);
- }
- }
- int query(int x)
- {
- int ret = 0;
- while (x > 0){
- ret += bit[x];
- x -= x&(-x);
- }
- return ret;
- }
- void solve(int head, int tail, int l, int r)
- {
- if (head > tail) return;
- if (l == r){
- for (int i = head; i <= tail; ++i){
- if (q[i].qt == 3) ans[q[i].index] = l;
- }
- return;
- }
- int mid = (l + r) >> 1;
- // 将所有<=mid的操作作一遍,tmp[i]存的是[head,tail]里<=mid的操作对询问的贡献
- for (int i = head; i <= tail; ++i){
- if (q[i].qt == 1 && q[i].y <= mid){
- add(q[i].x, 1);
- }
- else if (q[i].qt == 2 && q[i].y <= mid){
- add(q[i].x, -1);
- }
- else{
- tmp[i] = query(q[i].y) - query(q[i].x - 1);
- }
- }
- // 将操作撤销一下
- for (int i = head; i <= tail; ++i){
- if (q[i].qt == 1 && q[i].y <= mid){
- add(q[i].x, -1);
- }
- else if (q[i].qt == 2 && q[i].y <= mid){
- add(q[i].x, 1);
- }
- }
- // 将操作划分成两部分
- int l1=0, l2 = 0;
- for (int i = head; i <= tail; ++i){
- if (q[i].qt == 3){
- // 如果前面的数加上当前的数>=q[i].k,说明该询问的可行区间在[l,mid],往左划分
- if (q[i].cur + tmp[i] >= q[i].k){
- q1[++l1] = q[i];
- }
- else{
- // 否则往右划分,并记下贡献
- q[i].cur += tmp[i];
- q2[++l2] = q[i];
- }
- }
- else{
- if (q[i].y <= mid) q1[++l1] = q[i];
- else q2[++l2] = q[i];
- }
- }
- for (int i = 1; i <= l1; ++i) {
- q[head + i - 1] = q1[i];
- }
- for (int i = 1; i <= l2; ++i){
- q[head + l1 + i - 1] = q2[i];
- }
- solve(head, head + l1 - 1, l, mid);
- solve(head + l1, tail, mid + 1, r);
- }
- int main()
- {
- int T; cin >> T;
- while (T--)
- {
- scanf("%d%d", &n, &m);
- qtop = 0;tot = 0;
- for (int i = 1; i <= n; ++i){
- scanf("%d", a + i);
- b[tot++] = a[i];
- q[++qtop].qt = 1;
- q[qtop].x = i;
- q[qtop].y = a[i];
- }
- char cmd[4];
- int xi, yi,ki;
- ansid = 0;
- for (int i = 0; i < m; ++i){
- scanf("%s", cmd);
- if (cmd[0] == 'Q'){
- scanf("%d%d%d", &xi, &yi, &ki);
- q[++qtop].x = xi; q[qtop].y = yi; q[qtop].k = ki;
- q[qtop].qt = 3; q[qtop].cur = 0; q[qtop].index = ++ansid;
- }
- else{
- scanf("%d%d", &xi, &yi);
- q[++qtop].x = xi; q[qtop].y = a[xi]; q[qtop].qt = 2;
- q[++qtop].x = xi; q[qtop].y = yi; q[qtop].qt = 1;
- a[xi] = yi;
- b[tot++] = yi;
- }
- }
- sort(b, b + tot);
- bsize = unique(b, b + tot) - b;
- for (int i = 1; i <= qtop; ++i){
- if (q[i].qt == 1 || q[i].qt == 2){
- q[i].y = lower_bound(b, b + bsize, q[i].y) - b + 1;
- }
- }
- solve(1, qtop, 1, bsize);
- for (int i = 1; i <= ansid; ++i){
- printf("%d\n", b[ans[i]-1]);
- }
- }
- //system("pause");
- return 0;
- }
ZOJ2112 Dynamic Rankings(整体二分)的更多相关文章
- [bzoj1901][zoj2112][Dynamic Rankings] (整体二分+树状数组 or 动态开点线段树 or 主席树)
Dynamic Rankings Time Limit: 10 Seconds Memory Limit: 32768 KB The Company Dynamic Rankings has ...
- 【BZOJ1901】Dynamic Rankings [整体二分]
Dynamic Rankings Time Limit: 10 Sec Memory Limit: 128 MB[Submit][Status][Discuss] Description 给定一个含 ...
- BZOJ 1901 Zju2112 Dynamic Rankings ——整体二分
[题目分析] 上次用树状数组套主席树做的,这次用整体二分去水. 把所有的查询的结果一起进行二分,思路很好. [代码] #include <cstdio> #include <cstr ...
- BZOJ1901: Zju2112 Dynamic Rankings(整体二分 树状数组)
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 9094 Solved: 3808[Submit][Status][Discuss] Descript ...
- BZOJ 1901 Dynamic Rankings (整体二分+树状数组)
题目大意:略 洛谷传送门 这道题在洛谷上数据比较强 貌似这个题比较常见的写法是树状数组套主席树,动态修改 我写的是整体二分 一开始的序列全都视为插入 对于修改操作,把它拆分成插入和删除两个操作 像$C ...
- 洛谷$P2617\ Dynamic\ Rankings$ 整体二分
正解:整体二分 解题报告: 传送门$w$ 阿查询带修区间第$k$小不显然整体二分板子呗,,, 就考虑先按时间戳排序(,,,其实并不需要读入的时候就按着时间戳排的鸭$QwQ$ 每次二分出$mid$先把所 ...
- BZOJ.1901.Dynamic Rankings(整体二分)
题目链接 BZOJ 洛谷 (以下是口胡) 对于多组的询问.修改,我们可以发现: 假设有对p1,p2,p3...的询问,在这之前有对p0的修改(比如+1),且p0<=p1,p2,p3...,那么我 ...
- 【ZOJ2112】【整体二分+树状数组】带修改区间第k大
The Company Dynamic Rankings has developed a new kind of computer that is no longer satisfied with t ...
- ZOJ2112 Dynamic Rankings
题意 Dynamic Rankings Time Limit: 10 Seconds Memory Limit: 32768 KB The Company Dynamic Rankings ...
随机推荐
- Dapper基础增删查改、事务和存储过程
1.前言 Dapper是一个轻量级的orm框架,上手也非常的简单,它可以实体映射,所以先准备实体如下: public class Couser { public int id { get; set; ...
- global js库
var GLOBAL = {}; GLOBAL.namespace = function(str) { var arr = str.split("."), o = GLOBAL,i ...
- Python 协程与事件循环
Table of Contents 前言 协程 async & await 事件循环 asyncio 的事件循环 结语 参考链接 前言 Python 标准库 asyncio 是我目前接触过的最 ...
- python-成员修饰符
python的面相对象中,拥有3个成员,字段.方法.属性 class Foo: def __init__(self,name): #公有字段name在类中与类外均能调用 self.name = nam ...
- Python学习-django-ModelForm组件
ModelForm a. class Meta: model, # 对应Model的 fields=None, # 字段 exclude=None, # 排除字段 labels=None, # 提示信 ...
- Windows后续处理工作
1.远程桌面开启,应预先开启windows防火墙,并放行“远程桌面”(TCP 3389)端口,防止用户自行开启防火墙时操作错误. 2.防火墙高级安全-需放行ICMP 3.补丁更新,更新完重启 4.本地 ...
- leetcode_day02
任务二:删除排序数组中的重复项 原文链接:https://leetcode-cn.com/problems/remove-duplicates-from-sorted-array/ 最开始的解决思路: ...
- Homework-09 二维数组动态显示
思路 主要是把计算的函数由一次跑完全部改成一次一步 主要是把一个3重for循环改为能一步一次的实现 public int nstep(int n){ while((n--)!=0){ //n步长 // ...
- error MSB6006: “aapt.exe”已退出,代码为-1073741819
今天升级了Xamarin和Android SDK之后连模板程序生成都报这个错误,真是想剁手啊,最后在google同学的帮助下搜索到了Xamarin官方论坛上的回答 这个问题是生成工具版本选择的问题,似 ...
- 第十二篇:HTML基础
本篇内容 HTML概述 HTML常用基本标签 CSS格式引入 一. HTML概述 1.定义: HTML,超文本标记语言,写给浏览器的语言,目前网络上应用最广泛的语言.HTML也在不断的更新,最新版本已 ...