【BZOJ3110】K大数查询(整体二分)

题面

BZOJ

题解

看了很久整体二分

一直不知道哪里写错了

。。。

又把树状数组当成线段树区间加法来用了。。

整体二分还是要想清楚在干什么:

我们考虑第\(K\)大是什么

就是还有\(K-1\)个比他小

这样子就可以考虑二分之后如何\(check\)

当前二分出一个答案之后

按照时间顺序检查每个操作

如果是添加:

如果加进去的值比二分的答案要小

证明对结果没有贡献

直接丢到左区间里不管

否则线段树做区间加法

如果是修改

检查一下当前是否满足

然后分类丢到左右区间

总的来说

想清楚还是挺容易的

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<queue>
using namespace std;
#define ll long long
#define RG register
#define MAX 52000
#define lson (now<<1)
#define rson (now<<1|1)
inline int read()
{
RG int x=0,t=1;RG char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=-1,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return x*t;
}
struct Node
{
int clr;
int ly;
ll sum;
void clear(){clr=ly=sum=0;}
}t[MAX<<3];
int n,m,ans[MAX];
void putlazy(int now,int l,int r,int w)
{
t[now].sum+=w*(r-l+1);
t[now].ly+=w;
}
void clr(int now)
{
if(t[now].clr)
{
t[lson].clear();
t[rson].clear();
t[lson].clr=1;
t[rson].clr=1;
t[now].clr=0;
}
}
void pushdown(int now,int l,int r)
{
int mid=(l+r)>>1;
clr(now);
putlazy(lson,l,mid,t[now].ly);
putlazy(rson,mid+1,r,t[now].ly);
t[now].ly=0;
}
void Modify(int now,int l,int r,int L,int R)
{
pushdown(now,l,r);
if(l==L&&r==R){putlazy(now,l,r,1);return;}
t[now].sum+=R-L+1;
int mid=(l+r)>>1;
if(R<=mid)Modify(lson,l,mid,L,R);
else if(L>mid)Modify(rson,mid+1,r,L,R);
else{Modify(lson,l,mid,L,mid);Modify(rson,mid+1,r,mid+1,R);}
}
ll Query(int now,int l,int r,int L,int R)
{
pushdown(now,l,r);
if(L<=l&&r<=R)return t[now].sum;
int mid=(l+r)>>1;ll ret=0;
if(L<=mid)ret+=Query(lson,l,mid,L,R);
if(R>mid)ret+=Query(rson,mid+1,r,L,R);
return ret;
}
struct Ask{int opt,l,r,c,id;}p[MAX],p1[MAX],p2[MAX];
void Work(int L,int R,int l,int r)
{
if(L>R)return;
if(l==r)
{
for(int i=L;i<=R;++i)ans[p[i].id]=l;
return;
}
int mid=(l+r)>>1;
int t1=0,t2=0;
for(int i=L;i<=R;++i)
{
if(p[i].opt==1)
{
if(p[i].c<=mid)p1[++t1]=p[i];
else
{
p2[++t2]=p[i];
Modify(1,1,n,p[i].l,p[i].r);
}
}
else
{
ll ss=Query(1,1,n,p[i].l,p[i].r);
if(ss>=p[i].c)p2[++t2]=p[i];
else p[i].c-=ss,p1[++t1]=p[i];
}
}
for(int i=1;i<=t1;++i)p[L+i-1]=p1[i];
for(int i=1;i<=t2;++i)p[L+t1+i-1]=p2[i];
t[1].clear();t[1].clr=1;
Work(L,L+t1-1,l,mid);Work(L+t1,R,mid+1,r);
}
int main()
{
n=read();m=read();
int sum=0;
for(int i=1;i<=m;++i)
{
p[i].opt=read();p[i].l=read();p[i].r=read();p[i].c=read();
if(p[i].opt==2)p[i].id=++sum;
}
Work(1,m,-n,n);
for(int i=1;i<=sum;++i)printf("%d\n",ans[i]);
return 0;
}

【BZOJ3110】K大数查询(整体二分)的更多相关文章

  1. 【BZOJ-3110】K大数查询 整体二分 + 线段树

    3110: [Zjoi2013]K大数查询 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 6265  Solved: 2060[Submit][Sta ...

  2. BZOJ 3110 K大数查询 | 整体二分

    BZOJ 3110 K大数查询 题面 有N个位置,M个操作.操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c 如果是2 a b c形式,表示询问从第a个 ...

  3. [ZJJOI2013]K大数查询 整体二分

    [ZJJOI2013]K大数查询 链接 luogu 思路 整体二分. 代码 #include <bits/stdc++.h> #define ll long long using name ...

  4. BZOJ3110:[ZJOI2013]K大数查询(整体二分)

    Description 有N个位置,M个操作.操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c.如果是2 a b c形式,表示询问从第a个位置到第b个位 ...

  5. 【bzoj3110】[Zjoi2013]K大数查询 整体二分+树状数组区间修改

    题目描述 有N个位置,M个操作.操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c.如果是2 a b c形式,表示询问从第a个位置到第b个位置,第C大的数 ...

  6. P3332 [ZJOI2013]K大数查询 整体二分

    终于入门整体二分了,勉勉强强算是搞懂了一个题目吧. 整体二分很多时候可以比较好的离线处理区间\(K\)大值的相关问题.考虑算法流程: 操作队列\(arr\),其中有询问和修改两类操作. 每次在答案的可 ...

  7. BZOJ 3110: [Zjoi2013]K大数查询 [整体二分]

    有N个位置,M个操作.操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c如果是2 a b c形式,表示询问从第a个位置到第b个位置,第C大的数是多少. N ...

  8. BZOJ.3110.[ZJOI2013]K大数查询(整体二分 树状数组/线段树)

    题目链接 BZOJ 洛谷 整体二分求的是第K小(利用树状数组).求第K大可以转为求第\(n-K+1\)小,但是这样好像得求一个\(n\). 注意到所有数的绝对值\(\leq N\),将所有数的大小关系 ...

  9. [ZJOI2013]K大数查询——整体二分

    题目描述 有N个位置,M个操作.操作有两种,每次操作如果是: 1 a b c:表示在第a个位置到第b个位置,每个位置加上一个数c 2 a b c:表示询问从第a个位置到第b个位置,第C大的数是多少. ...

  10. BZOJ 3110 [Zjoi2013]K大数查询 ——整体二分

    [题目分析] 整体二分显而易见. 自己YY了一下用树状数组区间修改,区间查询的操作. 又因为一个字母调了一下午. 貌似树状数组并不需要清空,可以用一个指针来维护,可以少一个log 懒得写了. [代码] ...

随机推荐

  1. 调试 smallcorgi/Faster-RCNN_TF 的demo过程遇到的问题

    最近在调试faster R-CNN时,遇到了各种各样的问题.使用的算法库为https://github.com/smallcorgi/Faster-RCNN_TF 注:本文使用的是通过virtuale ...

  2. [记]Debian alias 设置, 不设置貌似有点不方便习惯

    备忘录,记录下. 不知道 当前有那些 alias 的话 直接输入 alias ,回车就可以看到 alias 列表. 终端输入: vim ~/bash_aliases 然后输入: # some more ...

  3. WinFom中经典小游戏(含源码)

    最近整理了若干经典的小游戏,无聊时可以打发时间.程序本身不大,练手非常不错,主要是GDI编程,主界面地址如下图所示 源码下载方式 1,关注微信公众号:小特工作室(也可直接扫描签名处二维码) 2,发送: ...

  4. Ubuntu14.04上安装Composer

    1,查看机子上有没有安装php 2,下载Composer的安装包 3,安装Composer 4,设置Composer全局可访问

  5. C++学习笔记第三天:类、虚函数、双冒号

    类 class Box { public: double length; // 盒子的长度 double breadth; // 盒子的宽度 double height; // 盒子的高度 }; 类成 ...

  6. qt Multimedia 模块类如何使用?

    qt 多媒体模块介绍 类名 英文描述 中文描述 QAudioBuffer Represents a collection of audio samples with a specific format ...

  7. PAT乙级1065 map

    思路:检查某个客人是否有伴侣,如果有,伴侣是否也出现即可. 注意:0个单身狗的时候,不要输出多余的'\n', 否则会出现格式错误. AC代码 #include <stdio.h> #inc ...

  8. hihoCoder 树结构判定(并查集)

    思路:树满足两个条件: 1.顶点数等于边数加一 2.所有的顶点在一个联通块 那么直接dfs或者并查集就可以了. AC代码 #include <stdio.h> #include<st ...

  9. CodeForces-747A

    从sqrt(n)枚举到1,一旦满足一定是差最小的数. AC代码: #include<cstdio> #include<cmath> int main(){ int n; whi ...

  10. CodeForces-749B

    给定3个坐标,求可能构成平行四边形的第四个点,枚举两个点,根据这两个点的横纵坐标差,来得到第四个点的坐标,注意生成的坐标需要判重. AC代码: #include<cstdio> #incl ...