HDU 5412 CRB and Queries 整体二分
来源:互联网 发布:炫舞卡坐骑软件 编辑:程序博客网 时间:2024/06/11 02:21
题目:
http://acm.hdu.edu.cn/showproblem.php?pid=5412
题意:
给定一个长度为n的序列,有以下两种操作:1 x y k,求区间[x,y]中的第k小数,2 x y,把位置x的元素替换为y。
思路:
用的整体二分。谈一下自己对整体二分的理解(如有错误请谅解):整体二分总体来说是分治,然后用二分枚举一个值,在分治的时候用这个枚举值来划分左右子区间。像求第k小数,二分枚举一个值,对于序列中的元素,如果小于等于枚举值,就划分到左子区间,否则就划分到右子区间;对于询问,判断当前枚举值时,统计询问区间中元素在左子区间中出现的个数,如果大于等于k的话,答案肯定在左子区间中,把这个查询也划分到左子区间中,否则的话,划分到右子区间中,可以发现右子区间的枚举值肯定是比当前枚举值大,意味着左子区间中的元素对于右子区间中询问贡献是固定的,可以直接减去这个贡献,然后再在右子区间中查找。另外这个题有修改操作,可以把修改看做删除原位置上的数,然后在原位置上再插入一个数,分解为两步,按顺序加入到操作队列中,对于序列初始值,可以看做只插入不删除,然后按静态的做就好了,因为操作队列是按时间序排的,这样一定是正确的。
这个题与ZOJ2112基本是一样的,不过那道题数据范围要小很多,特别是查询少了很多!于是那个题我用分块水了过去,这道题用分块就TLE了,毕竟查询太多了。以后查询多的不能用分块,毕竟这玩意其实就是个优美的暴力,查询少的可以尝试一下
#include <bits/stdc++.h>using namespace std;typedef long long ll;const int N = 100000 + 10, M = 100000 + 10;struct BIT{ int n, b[N]; void init(int _n) { n = _n; memset(b, 0, sizeof b); } void add(int i, int x) { while(i <= n) b[i] += x, i += i & -i; } int sum(int i) { int ans = 0; while(i > 0) ans += b[i], i -= i & -i; return ans; }} bit;struct node{ int x, y, k, id, type; void init(int _x, int _y, int _k, int _id, int _type) { x = _x, y = _y, k = _k, id = _id, type = _type; }} q[N+M*2], ql[N+M*2], qr[N+M*2];int a[N], ans[M];void divide_conquer(int st, int en, ll l, ll r){ if(st > en) return; if(l == r)//此时答案确定 { for(int i = st; i <= en; i++) if(q[i].type == 2) ans[q[i].id] = l; return; } ll mid = (l + r) >> 1; int kl = 0, kr = 0; for(int i = st; i <= en; i++) { if(q[i].type == 1)//序列中的元素 { if(q[i].x <= mid) { ql[kl++] = q[i]; bit.add(q[i].id, q[i].y);//树状数组统计 } else qr[kr++] = q[i]; } else//查询操作 { int num = bit.sum(q[i].y) - bit.sum(q[i].x - 1); if(num >= q[i].k) ql[kl++] = q[i]; else { q[i].k -= num; qr[kr++] = q[i]; } } } for(int i = 0; i < kl; i++)//还原树状数组 if(ql[i].type == 1) bit.add(ql[i].id, -ql[i].y); for(int i = 0; i < kl; i++) q[st+i] = ql[i]; for(int i = 0; i < kr; i++) q[st+kl+i] = qr[i]; divide_conquer(st, st + kl - 1, l, mid); divide_conquer(st + kl, en, mid + 1, r);}int main(){ int n, m; while(~ scanf("%d", &n)) { bit.init(n); int tot = 0, x, y, k; char ch; for(int i = 1; i <= n; i++) { scanf("%d", &a[i]); q[++tot].init(a[i], 1, 0, i, 1); } scanf("%d", &m); for(int i = 1; i <= m; i++) { scanf(" %c%d%d", &ch, &x, &y); if(ch == '2') { scanf("%d", &k); q[++tot].init(x, y, k, i, 2); } else { q[++tot].init(a[x], -1, 0, x, 1); q[++tot].init(y, 1, 0, x, 1); a[x] = y; } } memset(ans, -1, sizeof ans); divide_conquer(1, tot, INT_MIN, INT_MAX); for(int i = 1; i <= m; i++) if(ans[i] != -1) printf("%d\n", ans[i]); } return 0;}
阅读全文
0 0
- Hdu-5412 CRB and Queries(整体二分)
- HDU 5412 CRB and Queries 整体二分
- Hdu CRB and Queries(整体二分)
- HDU 5412 CRB and Queries【整体二分+树状数组】
- HDU 5412 CRB and Queries(整体二分)
- [HDU 5412] CRB and Queries (整体二分)
- HDU 5412 CRB and Queries(整体二分 | CDQ分治)
- HDU 5412 CRB and Queries 求区间第k小 CDQ分治+整体二分
- hdu 5412 CRB and Queries(动态求区间第k小+整体二分)
- HDU 5412 CRB and Queries (Kth number 整体二分 动态转静态)
- 整体二分,区间第K小(CRB and Queries,HDU 5412)
- hdu5412--CRB and Queries(整体二分)
- 整体二分 hdu5412 CRB and Queries
- hdu5412 CRB and Queries (整体二分)
- HDU 5412 CRB and Queries && BZOJ 3110: [Zjoi2013]K大数查询 (整体二分+树状数组/线段树)
- hdu 5412 CRB and Queries
- hdu5412:CRB and Queries (整体二分+树状数组)
- hdu 5412 CRB and Queries(动态区间第k大值,区间能修改)(整体二分,树状数组套平衡树,线段树套treap)
- PAT (Advanced Level) Practise 1118 Birds in Forest (25)
- 浅析angular,react,vue.js jQuery使用区别
- Android studio 创建本地文件时没有权限的怪现象
- idea javaweb项目导入标签库
- LeetCode 62. Unique Paths
- HDU 5412 CRB and Queries 整体二分
- 安装本地存在的包到maven中
- github提交代码无法改变远程仓库路径
- 系统调用实现Linux命令 ls -al
- MLP(多层感知器)神经网络
- Python语法第2讲:条件分支与循环控制
- ajax全局事件引用方式以及各个事件(全局/局部)执行顺序
- Ubuntu 安装及卸载GIMP步骤
- 【BZOJ】1787 [Ahoi2008]Meet 紧急集合 LCA