BZOJ 3110 ZJOI 2013 K大数查询 树套树(权值线段树套区间线段树)
题目大意:有一些位置。这些位置上能够放若干个数字。
如今有两种操作。
1.在区间l到r上加入一个数字x
2.求出l到r上的第k大的数字是什么
思路:这样的题一看就是树套树,关键是怎么套,怎么写。(话说我也不会来着。。)最easy想到的方法就是区间线段树套一个权值线段树。可是区间线段树上的标记就会变得异常复杂。所以我们就反过来套,用权值线段树套区间线段树。
这样改动操作在外线段树上就变成了单点改动。外线段树就不用维护标记了。在里面的区间线段树上维护标记就easy多了。详细实现见代码。
CODE:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define MAX 50010
#define CNT (r - l + 1)
using namespace std; int total,asks; struct ValSegTree{
ValSegTree *son[2];
int cnt,c; ValSegTree() {
son[0] = son[1] = NULL;
cnt = c = 0;
}
void PushDown(int k) {
if(son[0] == NULL) son[0] = new ValSegTree();
if(son[1] == NULL) son[1] = new ValSegTree();
if(c) {
son[0]->cnt += c * (k - (k >> 1));
son[0]->c += c;
son[1]->cnt += c * (k >> 1);
son[1]->c += c;
c = 0;
}
}
void Modify(int l,int r,int x,int y) {
if(l == x && r == y) {
cnt += CNT;
c++;
return ;
}
PushDown(CNT);
int mid = (l + r) >> 1;
if(y <= mid) son[0]->Modify(l,mid,x,y);
else if(x > mid) son[1]->Modify(mid + 1,r,x,y);
else {
son[0]->Modify(l,mid,x,mid);
son[1]->Modify(mid + 1,r,mid + 1,y);
}
cnt = son[0]->cnt + son[1]->cnt;
}
int Ask(int l,int r,int x,int y) {
if(!cnt) return 0;
if(l == x && r == y) return cnt;
PushDown(CNT);
int mid = (l + r) >> 1;
if(y <= mid) return son[0]->Ask(l,mid,x,y);
if(x > mid) return son[1]->Ask(mid + 1,r,x,y);
int left = son[0]->Ask(l,mid,x,mid);
int right = son[1]->Ask(mid + 1,r,mid + 1,y);
return left + right;
}
};
struct IntSegTree{
IntSegTree *son[2];
ValSegTree *root; IntSegTree() {
son[0] = son[1] = NULL;
root = new ValSegTree();
}
void Modify(int l,int r,int _l,int _r,int x) {
root->Modify(1,total,_l,_r);
if(l == r) return ;
int mid = (l + r) >> 1;
if(son[0] == NULL) son[0] = new IntSegTree();
if(son[1] == NULL) son[1] = new IntSegTree();
if(x <= mid) son[0]->Modify(l,mid,_l,_r,x);
else son[1]->Modify(mid + 1,r,_l,_r,x);
}
int Ask(int l,int r,int _l,int _r,int k) {
if(l == r) return l;
int mid = (l + r) >> 1;
if(son[0] == NULL) son[0] = new IntSegTree();
if(son[1] == NULL) son[1] = new IntSegTree();
int temp = son[1]->root->Ask(1,total,_l,_r);
if(k > temp) return son[0]->Ask(l,mid,_l,_r,k - temp);
else return son[1]->Ask(mid + 1,r,_l,_r,k);
}
}root; int main()
{
cin >> total >> asks;
for(int flag,x,y,z,i = 1;i <= asks; ++i) {
scanf("%d%d%d%d",&flag,&x,&y,&z);
if(flag == 1) root.Modify(1,total,x,y,z);
else printf("%d\n",root.Ask(1,total,x,y,z));
}
return 0;
}
BZOJ 3110 ZJOI 2013 K大数查询 树套树(权值线段树套区间线段树)的更多相关文章
- [BZOJ 3110] [ZJOI 2013] K大数查询
Description 有 \(N\) 个位置,\(M\) 个操作.操作有两种,每次操作如果是: 1 a b c:表示在第 \(a\) 个位置到第 \(b\) 个位置,每个位置加入一个数 \(c\): ...
- [BZOJ 3110] [luogu 3332] [ZJOI 2013]k大数查询(权值线段树套线段树)
[BZOJ 3110] [luogu 3332] [ZJOI 2013]k大数查询(权值线段树套线段树) 题面 原题面有点歧义,不过从样例可以看出来真正的意思 有n个位置,每个位置可以看做一个集合. ...
- 【34.14%】【BZOJ 3110】 [Zjoi2013]K大数查询
Time Limit: 20 Sec Memory Limit: 512 MB Submit: 5375 Solved: 1835 [Submit][Status][Discuss] Descript ...
- 解题:ZJOI 2013 K大数查询
题面 树套树,权值线段树套序列线段树,每次在在权值线段树上的每棵子树上做区间加,查询的时候左右子树二分 本来想两个都动态开点的,这样能体现树套树在线的优越性.但是常数太大惹,所以外层直接固定建树了QA ...
- 【BZOJ 3110】 [Zjoi2013]K大数查询(整体二分)
[题目] Description 有N个位置,M个操作.操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c如果是2 a b c形式,表示询问从第a个位置到 ...
- 数据结构(树套树):ZJOI 2013 K大数查询
有几个点卡常数…… 发现若第一维为位置,第二维为大小,那么修改时第一维修改区间,查询时第一维查询区间,必须挂标记.而这种情况下标记很抽象,而且Push_down不是O(1)的,并不可行. 那要怎么做呢 ...
- BZOJ 3110:[Zjoi2013]K大数查询(整体二分)
http://www.lydsy.com/JudgeOnline/problem.php?id=3110 题意:-- 思路:其实和之前POJ那道题差不多,只不过是换成区间更新,而且是第k大不是第k小, ...
- [ZJOI 2013] K大数查询
[题目链接] https://www.lydsy.com/JudgeOnline/problem.php?id=3110 [算法] 整体二分 + 线段树 时间复杂度 : O(NlogN ^ 2) [代 ...
- 【bzoj 3110】[Zjoi2013]K大数查询
Description 有N个位置,M个操作.操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c.如果是2 a b c形式,表示询问从第a个位置到第b个位 ...
随机推荐
- hdu 2104
#include <iostream> using namespace std; int gcd(int a,int b) { return (b?gcd(b,a%b):a); } int ...
- maven 配置报错 JAVA_HOME not found in your environment
最近比较空,想研究下spring mvc,于是编按照教程一步一步配置开发环境.配置maven完成后,运行命令mvn -v的时候,竟然报错.错误信息如下: Error: JAVA_HOME not fo ...
- 怎样取得数组对象和arralist 的长度
数组用length属性 ArrayList用size()方法
- Knockoutjs官网翻译系列(二) Observable 数组
承接前文,前文书说道了KO框架中如何使用observable的视图模型属性来与UI元素进行绑定并自动进行双向更新的事儿.observable属性除了服务基础数据类型之外,还定义了专门为服务数组类型的o ...
- javascript sort()与reverse()
javascript 中提供了两个对数据进行排序的方法,即sort()和reverse() 在理解的时候犯了一个非常低级的错误,现记录如下: reverse()不包括排序的功能,只是把原来的数组反转. ...
- [转载] 关于“淘宝应对"双11"的技术架构分析”
微博上一篇最新的关于“淘宝应对"双11"的技术架构分析”.数据产品的一个最大特点是数据的非实时写入.
- RBAC角色权限设计思路
1 设计思路 为了设计一套具有较强可扩展性的用户认证管理,需要建立用户.角色和权限等数据库表,并且建立之间的关系,具体实现如下. 1.1 用户 用户仅仅是纯粹的用户,用来记录用户相关信息,如用户名.密 ...
- HTML5数据存储
介绍两种对象使用方法: sessionStorage方法如果关闭了浏览器,这个保存的数据就丢失. 1.sessionStorage 保存数据:sessionStorage.setItem(key,va ...
- iScroll 下拉刷新
<!doctype html> <html> <head> <meta charset="utf-8"> <script ty ...
- 在PHP中获取日期和时间
PHP提供了多种获取时间和日期的函数,除了通过time()函数获取当前的UNIX时间戳外,调用getdate()函数确定当前时间,通过gettimeofday()函数获取某一天中的具体时间.此外,在P ...