BZOJ3110[Zjoi2013]K大数查询——权值线段树套线段树
题目描述
有N个位置,M个操作。操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c
如果是2 a b c形式,表示询问从第a个位置到第b个位置,第C大的数是多少。
输入
第一行N,M
接下来M行,每行形如1 a b c或2 a b c
输出
输出每个询问的结果
样例输入
1 1 2 1
1 1 2 2
2 1 1 2
2 1 1 1
2 1 2 3
样例输出
2
1
提示
【样例说明】
第一个操作 后位置 1 的数只有 1 , 位置 2 的数也只有 1 。 第二个操作 后位置 1
的数有 1 、 2 ,位置 2 的数也有 1 、 2 。 第三次询问 位置 1 到位置 1 第 2 大的数 是
1 。 第四次询问 位置 1 到位置 1 第 1 大的数是 2 。 第五次询问 位置 1 到位置 2 第 3
大的数是 1 。
N,M<=50000,N,M<=50000
a<=b<=N
1操作中abs(c)<=N
2操作中c<=Maxlongint
显然一棵线段树或平衡树无法维护这道题的操作,那么考虑树套树。
一开始可能会想将维护序列的线段树放在外层,然后将维护序列每个点各种权值的权值线段树放在内层。
这样修改操作就是外层线段树区间修改,内层线段树单点修改,很好操作。
但你发现无法完成询问操作,如果用二分答案来解决的话时间复杂度就是O(nlogn^3)的了。
既然询问第k大,那么显然权值线段树对于这种操作更为擅长,我们将权值线段树放在外层,将维护序列的线段树放在内层。
这样修改就变成了外层线段树单点修改,内层线段树区间修改,同样很好操作。
对于询问,我们每查询到权值线段树的一个节点先在这个点左子节点的内层线段树上区间查找,即找出序列上询问区间中权值小于某个值的数量,再与k判断来决定往左走还是往右走。
#include<set>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<bitset>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
int n,m;
int opt;
int cnt;
int a,b;
ll c;
ll s[20000010];
int root[2000010];
ll sum[20000010];
int ls[20000010];
int rs[20000010];
inline void pushup(int rt)
{
sum[rt]=sum[ls[rt]]+sum[rs[rt]];
}
inline void pushdown(int rt,int l,int r)
{
if(s[rt])
{
int mid=(l+r)>>1;
if(!ls[rt])
{
ls[rt]=++cnt;
}
if(!rs[rt])
{
rs[rt]=++cnt;
}
s[ls[rt]]+=s[rt];
s[rs[rt]]+=s[rt];
sum[ls[rt]]+=s[rt]*(mid-l+1);
sum[rs[rt]]+=s[rt]*(r-mid);
s[rt]=0;
}
}
inline void change(int &rt,int l,int r,int L,int R)
{
if(!rt)
{
rt=++cnt;
}
if(L<=l&&r<=R)
{
sum[rt]+=(r-l+1);
s[rt]++;
return ;
}
pushdown(rt,l,r);
int mid=(l+r)>>1;
if(L<=mid)
{
change(ls[rt],l,mid,L,R);
}
if(R>mid)
{
change(rs[rt],mid+1,r,L,R);
}
pushup(rt);
}
inline ll find(int rt,int l,int r,int L,int R)
{
if(!rt)
{
return 0;
}
if(L<=l&&r<=R)
{
return sum[rt];
}
pushdown(rt,l,r);
int mid=(l+r)>>1;
ll res=0;
if(L<=mid)
{
res+=find(ls[rt],l,mid,L,R);
}
if(R>mid)
{
res+=find(rs[rt],mid+1,r,L,R);
}
return res;
}
inline void insert(int rt,int l,int r,int k,int L,int R)
{
change(root[rt],1,n,L,R);
if(l==r)
{
return ;
}
int mid=(l+r)>>1;
if(k<=mid)
{
insert(rt<<1,l,mid,k,L,R);
}
else
{
insert(rt<<1|1,mid+1,r,k,L,R);
}
}
inline int query(int rt,int l,int r,ll k,int L,int R)
{
if(l==r)
{
return l;
}
int mid=(l+r)>>1;
ll res=find(root[rt<<1|1],1,n,L,R);
if(res<k)
{
return query(rt<<1,l,mid,k-res,L,R);
}
else
{
return query(rt<<1|1,mid+1,r,k,L,R);
}
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
scanf("%d",&opt);
scanf("%d%d%lld",&a,&b,&c);
if(a>b)
{
swap(a,b);
}
if(opt==1)
{
c=(int)c;
insert(1,0,2*n,c+n,a,b);
}
else
{
printf("%d\n",query(1,0,2*n,c,a,b)-n);
}
}
}
BZOJ3110[Zjoi2013]K大数查询——权值线段树套线段树的更多相关文章
- 【bzoj3110】[Zjoi2013]K大数查询 权值线段树套区间线段树
题目描述 有N个位置,M个操作.操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c.如果是2 a b c形式,表示询问从第a个位置到第b个位置,第C大的数 ...
- 洛谷P3332 [ZJOI2013]K大数查询 权值线段树套区间线段树_标记永久化
Code: #include <cstdio> #include <algorithm> #include <string> #include <cstrin ...
- [BZOJ 3110] [luogu 3332] [ZJOI 2013]k大数查询(权值线段树套线段树)
[BZOJ 3110] [luogu 3332] [ZJOI 2013]k大数查询(权值线段树套线段树) 题面 原题面有点歧义,不过从样例可以看出来真正的意思 有n个位置,每个位置可以看做一个集合. ...
- BZOJ3110[Zjoi2013]K大数查询(树状数组+整体二分)
3110 [Zjoi2013]K大数查询 有N个位置,M个操作.操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c如果是2 a b c形式,表示询问从第a ...
- bzoj3110: [Zjoi2013]K大数查询 【树套树,标记永久化】
//========================== 蒟蒻Macaulish:http://www.cnblogs.com/Macaulish/ 转载要声明! //=============== ...
- BZOJ3110 [Zjoi2013]K大数查询 树套树 线段树 整体二分 树状数组
欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ3110 题意概括 有N个位置,M个操作.操作有两种,每次操作如果是1 a b c的形式表示在第a个位 ...
- bzoj3110 [Zjoi2013]K大数查询——线段树套线段树
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3110 外层权值线段树套内层区间线段树: 之所以外层权值内层区间,是因为区间线段树需要标记下传 ...
- BZOJ3110: [Zjoi2013]K大数查询
喜闻乐见的简单树套树= =第一维按权值建树状数组,第二维按下标建动态开点线段树,修改相当于第二维区间加,查询在树状数组上二分,比一般的线段树还短= =可惜并不能跑过整体二分= =另外bzoj上的数据有 ...
- [BZOJ3110] [Zjoi2013] K大数查询 (树套树)
Description 有N个位置,M个操作.操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c如果是2 a b c形式,表示询问从第a个位置到第b个位置 ...
随机推荐
- 【Atcoder yahoo-procon2019-qual D】 Ears
Atcoder yahoo-procon2019-qual D 题意:给你\(L\)个耳朵(???),以及一条范围从\(0\)到\(L\)的数轴,你可以选择一个出发点,从该点开始随意走动,如果经过了\ ...
- 关于LED效率,这4点你应该知道
关于LED效率,这4点你应该知道 发布时间:2017-08-22 12:09:35 原创:中国LED网 内容概要: 1. 这些灯的一些光通过转换器或磷光体转换成较长波长(绿色.黄色和红色光)的光,将所 ...
- SQLSERVER 中sp_who, sp_who2和sp_who3(转载)
sp_who可以返回如下信息: (可选参数LoginName, 或active代表活动会话数)Spid (系统进程ID)status (进程状态)loginame (用户登录名)hostname(用户 ...
- 如何下载google play商店里面的app?
如何不FQ的下载这国际版的app呢? 方法如下: https://androidappsapk.co/category/apps/ 你可以直接登入这个网站,下载你所需要的国际版的软件. 就像是踏入一个 ...
- Luogu3825 NOI2017 游戏 2-SAT
传送门 第一眼看上去似乎是一个3-SAT问题 然而\(d \leq 8\)给我们的信息就是:暴力枚举 枚举\(x\)型地图变成\(a\)型地图还是\(b\)型地图(实际上不要枚举\(c\),因为\(a ...
- VM下设置CenOS为静态IP
在本机利用VM启动了4台虚拟机来搭建zookeeper集群,但是每次电脑重启后,虚拟机的IP都会变化,现在想来固定每台虚拟机的IP. 1.Step1:查看网关和子网掩码 记住选用NAT模式,点击NAT ...
- 【noi.ac】#309. Mas的童年
#309. Mas的童年 链接 分析: 求$max \{sj + (s_i \oplus s_j)\}$ 因为$a + b = a \oplus b + (a \& b) \times 2$ ...
- .Net版本依赖之坑引发的搜查
前言 今天上午,一个客户反馈XX消息没有推送到第三方链接.于是我查看了推送日志列表,并没有今天的.接着登录服务器查询文件日志,看到了记录.我们的代码步骤是消息先推送到消息队列,消费消息队列时,记录文件 ...
- Lustre文件系统部署和应用探索
1. Lustre文件系统概述 2. Lustre文件系统部署 2.1 基本环境 本篇博客将在KVM虚拟机中部署Lustre文件系统. 操作系统版本为CentOS6.5_x86_64.Lustre软件 ...
- Jmeter(三十一)_数据驱动,业务关联
这种数据驱动的本质是:将测试的case,参数,url,预期结果,存储于本地excel中.运行脚本时,从文件中获取预期结果,将实际结果与预期结果比较,将实际结果,比较结果,响应状态码回写excel. 一 ...