【BZOJ3110】【Zjoi2013】K大数查询 - 2
之前用权值线段树套区间线段树水过,现在再练习一下整体二分
原题:
有N个位置,M个操作。操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c
如果是2 a b c形式,表示询问从第a个位置到第b个位置,第C大的数是多少。
N,M≤50000
对于每个1操作,abs(k)≤10^9
对于每个2操作,保证k≤所询问区间内数的个数的总数
这个数据是经过妹主席强化的,不过用整体二分解决的话没什么区别
整体二分这个东西呢,和cdq分治挺像的,我做得题少,也不好说出他们的区别
这题首先先按时间轴排序,其实并不用排序,输入顺序即可,第k大使用整体二分查找
具体过程呢,就是每次递归有两个范围,x,y表示时间轴,l,r表示数的范围
然后mid=(l+r)>>1,按照时间轴递增顺序,如果插入操作的值>mid就给插入操作的区间都++并分到右边,否则分到左边
查询操作就查询查询操作要查询的范围中的值(也就是这次递归中在查询区间中插入的个数),如果这个值<=查询的k,就什么也不动分到左边,否则k-=查询出的个数并分到右边
最后如果l==r,在x到y区间中的询问答案就是l
因为这里是使用两个栈来进行左右划分,设左边的栈顶为t1,左边的时间轴就被分成x,x+t1-1,右边分成x+t1,y,所以这里在每次递归开始的时候要判断x>y时直接退出
我做这道题的时候出现了一些问题:
栈当然要开全局,栈顶也可以开全局,但是进行左右划分的时候不能用全局的栈顶来划分!因为进行左边的递归,开始右边的递归的时候,范围本来应该是x+t1,y,但是这里的t1在进行左边递归的时候被改变了,这个时候就会发生问题
线段树区间修改要push_up
代码:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<vector>
using namespace std;
int rd(){int z=,mk=; char ch=getchar();
while(ch<''||ch>''){if(ch=='-')mk=-; ch=getchar();}
while(ch>=''&&ch<=''){z=(z<<)+(z<<)+ch-''; ch=getchar();}
return z*mk;
}
const int oo=;
struct dcd{int x,l,r,v,mk;}a[];
int n,m;
int ans[];
dcd q[][]; int hd[];
int v[],dt[];
void pshd(int x,int l,int r){
int md=(l+r)>>;
v[x<<]+=dt[x]*(md-l+),v[x<<|]+=dt[x]*(r-md);
dt[x<<]+=dt[x],dt[x<<|]+=dt[x];
dt[x]=;
}
void mdf(int x,int xx,int yy,int l,int r,int vv){
if(xx==l && yy==r){ v[x]+=vv*(r-l+),dt[x]+=vv; return ;}
pshd(x,xx,yy); int md=(xx+yy)>>;
if(l<=md && r>md) mdf(x<<,xx,md,l,md,vv),mdf(x<<|,md+,yy,md+,r,vv);
else if(r<=md) mdf(x<<,xx,md,l,r,vv);
else mdf(x<<|,md+,yy,l,r,vv);
v[x]=v[x<<]+v[x<<|];
}
int qr(int x,int xx,int yy,int l,int r){
if(xx==l && yy==r) return v[x];
pshd(x,xx,yy); int md=(xx+yy)>>;
if(l<=md && r>md) return qr(x<<,xx,md,l,md)+qr(x<<|,md+,yy,md+,r);
else if(r<=md) return qr(x<<,xx,md,l,r);
else return qr(x<<|,md+,yy,l,r);
}
void whlbnr(int x,int y,long long l,long long r){
if(x>y) return ;
if(l==r){
for(int i=x;i<=y;++i)if(a[i].mk==) ans[a[i].x]=l;
return ;
}
long long tmp,md=(l+r)>>;
hd[]=hd[]=;
for(int i=x;i<=y;++i){
if(a[i].mk==){
if(a[i].v>md) q[++hd[]][]=a[i],mdf(,,n,a[i].l,a[i].r,);
else q[++hd[]][]=a[i];
}
else{
if((tmp=qr(,,n,a[i].l,a[i].r))<a[i].v) a[i].v-=tmp,q[++hd[]][]=a[i];
else q[++hd[]][]=a[i];
}
}
for(int i=x;i<=y;++i)if(a[i].mk== && a[i].v>md) mdf(,,n,a[i].l,a[i].r,-);
for(int i=;i<hd[];++i) a[x+i]=q[i+][];
for(int i=;i<hd[];++i) a[x+hd[]+i]=q[i+][];
int t1=hd[];
whlbnr(x,x+t1-,l,md);
whlbnr(x+t1,y,md+,r);
//for(int i=x;i<=y;++i)if(a[i].mk==1 && a[i].v>((md+1+r)>>1)) mdf(1,1,n,a[i].l,a[i].r,1);
//whlbnr(x,x+hd[0]-1,l,md),whlbnr(x+hd[0],y,md+1,r);
}
int main(){//freopen("ddd.in","r",stdin);
cin>>n>>m;
for(int i=;i<=m;++i) a[i].mk=rd(),a[i].l=rd(),a[i].r=rd(),a[i].v=rd()+(a[i].mk==?oo:),a[i].x=i;
whlbnr(,m,,oo<<);
//for(int i=1;i<=m;++i)if(a[i].mk==2) printf("%d ",a[i].v);
for(int i=;i<=m;++i)if(ans[i]) printf("%d\n",ans[i]-oo);
return ;
}
【BZOJ3110】【Zjoi2013】K大数查询 - 2的更多相关文章
- BZOJ3110[Zjoi2013]K大数查询(树状数组+整体二分)
3110 [Zjoi2013]K大数查询 有N个位置,M个操作.操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c如果是2 a b c形式,表示询问从第a ...
- BZOJ3110 [Zjoi2013]K大数查询 树套树 线段树 整体二分 树状数组
欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ3110 题意概括 有N个位置,M个操作.操作有两种,每次操作如果是1 a b c的形式表示在第a个位 ...
- BZOJ3110: [Zjoi2013]K大数查询
喜闻乐见的简单树套树= =第一维按权值建树状数组,第二维按下标建动态开点线段树,修改相当于第二维区间加,查询在树状数组上二分,比一般的线段树还短= =可惜并不能跑过整体二分= =另外bzoj上的数据有 ...
- [BZOJ3110][ZJOI2013]K大数查询(整体二分)
BZOJ Luogu sol 整体二分,其实很简单的啦. 对所有询问二分一个答案mid,把所有修改操作中数字大于mid的做一个区间覆盖(区间加1) 查询就是区间查询 然后左右分一分即可 注意是第k大 ...
- BZOJ3110[Zjoi2013]K大数查询——权值线段树套线段树
题目描述 有N个位置,M个操作.操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c如果是2 a b c形式,表示询问从第a个位置到第b个位置,第C大的数是 ...
- bzoj3110: [Zjoi2013]K大数查询 【树套树,标记永久化】
//========================== 蒟蒻Macaulish:http://www.cnblogs.com/Macaulish/ 转载要声明! //=============== ...
- bzoj3110 [Zjoi2013]K大数查询——线段树套线段树
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3110 外层权值线段树套内层区间线段树: 之所以外层权值内层区间,是因为区间线段树需要标记下传 ...
- bzoj3110: [Zjoi2013]K大数查询 【cdq分治&树套树】
模板题,折腾了许久. cqd分治整体二分,感觉像是把询问分到答案上. #include <bits/stdc++.h> #define rep(i, a, b) for (int i = ...
- BZOJ3110:[ZJOI2013]K大数查询(整体二分)
Description 有N个位置,M个操作.操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c.如果是2 a b c形式,表示询问从第a个位置到第b个位 ...
- 【树套树】bzoj3110 [Zjoi2013]K大数查询
题解很多,实现起来以外地简洁.内层的区间线段树上用了标记永久化. #include<cstdio> using namespace std; #define N 50001 struct ...
随机推荐
- C#匿名对象序列化
//匿名对象序列化 }; Console.WriteLine(JsonConvert.SerializeObject(obj)); //匿名集合序列化 List<object> list ...
- JPA、SpringData JPA 、Hibernate和Mybatis 的区别和联系
一.JPA 概述 1. Java Persistence API(Java 持久层 API):用于对象持久化的 API 2. 作用:使得应用程序以统一的方式访问持久层 3. 前言中提到了 Hibern ...
- php正则表达式的三个最基本原则分享
我个人认为,正则表达式的常规用法可以分为如下三个最基本的原则:1.找谁.2.怎么找.3.找它干什么. 接下来,我分享一下一个正则表达式分三个部分: 原子字符 . 匹配除换行符以外的任意字符 \w 匹配 ...
- [Android教程] Cordova开发App入门(二)使用热更新插件
前言 不知各位遇没遇到过,刚刚发布的应用,突然发现了一个隐藏极深的“碧油鸡(BUG)”,肿么办!肿么办!肿么办!如果被老板发现,一定会让程序员哥哥去“吃鸡”.但是想要修复这个“碧油鸡”,就必须要重新打 ...
- 3-20 标准库:find库; 学习编程语言3节课(大多是旧识,全*栈)3-21 面向对象. Percent Strings; 元编程和Rails的相互理解
Find The Find module supports the top-down traversal of a set of file paths.(一系列文件的路径的遍历) find(*path ...
- 学习总结(ASP.NET MVC 5)
1. 无论什么时候,如果要写一个新的 MVC 的程序(网站),打开VS之后第一步永远都是“创建新的 ASP.NET MVC 项目” (“新建项目”—→“Web(Visual C#)”—→“ASP.NE ...
- EBS标准的查看供应商地址
--获取供应商PARTY_ID SELECT * FROM HZ_PARTIES HP WHERE HP.PARTY_NAME='XXXXXX' VO数据源:oracle.apps.pos.suppl ...
- kernel jenkins build script
#!/bin/bash #gcc: site="https://releases.linaro.org" #https://releases.linaro.org/componen ...
- 团队NABCD
NABCD 你的创意解决了用户的什么需求?(N) 每学期开学同学们都有相同的困难:我该选哪几门课?这门课到底是做什么的?有时候上一届的学长学姐会告诉我们他们觉得好的课,但这并不全面.所以我们需要一个平 ...
- Python3 urllib抓取指定URL的内容
最近在研究Python,熟悉了一些基本语法和模块的使用:现在打算研究一下Python爬虫.学习主要是通过别人的博客和自己下载的一下文档进行的,自己也写一下博客作为记录学习自己过程吧.Python代码写 ...