BZOJ传送门
Time Limit: 20 Sec Memory Limit: 512 MB
Submit: 3134 Solved: 1326
[Submit][Status][Discuss]
Description
有N个位置,M个操作。操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c
如果是2 a b c形式,表示询问从第a个位置到第b个位置,第C大的数是多少。

Input
第一行N,M
接下来M行,每行形如1 a b c或2 a b c

Output
输出每个询问的结果

Sample Input
2 5
1 1 2 1
1 1 2 2
2 1 1 2
2 1 1 1
2 1 2 3

Sample Output
1
2
1

HINT
【样例说明】
第一个操作 后位置 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操作中abs(c)<=Maxlongint

Source

读了半天题都读错了QuQ,果然是我语文不好,返回的是第K大数的位置

第一道整体二分,用了离线处理(貌似网上整体二分的资料不多?),先思考如果只有一个询问,如何二分?很简单嘛,在[L,R]的区间中取M=(L+R)>>1,计算在[L,M]区间中比询问的数大的有多少个。而整体二分,自然要整体,在二分区间的同时将所有询问一起二分处理。下面就是主要的思路

  • 如果二分的区间L==R那么答案在这个区间的全部为L(递归出口1)
  • 如果(l>r)返回(递归出口2)
  • 将询问分类,0类的答案在[L,M]中,1类的答案在[M+1,R]中
  • 如果是增加类型,考虑它的贡献如果v>M,就在[q.l,q.r]中每位添加1,归为1类,否则归为0类
  • 如果是查询类型,考虑答案位置,统计区间中比v大的个数,如果v<=s,答案在[M+1,R]中,归为1类,否则答案在[L,M]中,归为0类

对每一个询问我们都需要判定一下,以决定它被划分到哪一个答案的区间里。这个判定过程就是通过比较比二分的M大的数的个数和v。同时我们看到,如果比二分的M大的数的个数小于v了,我们是要去寻找小的答案,那么这些比M大的数在以后的递归里始终会对答案有贡献,所以我们没必要去做重复的工作,只需要把这些数的个数累积到贡献里,以后递归的时候就不用考虑这些数了 摘录自ZigZag Blog

  • 每次清空线段树要打标记,不能硬清
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
#define N 50005
#define lc o*2
#define rc o*2+1
#define done seg.ql=q[i].l,seg.qr=q[i].r
struct SegmentTree{int ql,qr;bool clr[N<<2];int add[N<<2],sum[N<<2];inline void init(){sum[1]=add[1]=0,clr[1]=1;}inline void updata(int o){sum[o]=sum[lc]+sum[rc];}inline void pushdown(int o,int L,int R){if(clr[o]){sum[lc]=sum[rc]=add[lc]=add[rc]=0,clr[lc]=clr[rc]=1,clr[o]=0;}int M=(L+R)>>1;if(add[o]){add[lc]+=add[o],add[rc]+=add[o];sum[lc]+=(M-L+1)*add[o],sum[rc]+=(R-M)*add[o];add[o]=0;}}void Add(int o,int L,int R){if(ql<=L&&R<=qr){add[o]++,sum[o]+=(R-L+1);return;}int M=(L+R)>>1;pushdown(o,L,R);if(ql<=M) Add(lc,L,M);if(qr>M) Add(rc,M+1,R);updata(o);}int Query(int o,int L,int R){if(ql<=L&&R<=qr){return sum[o];}pushdown(o,L,R);int res=0,M=(L+R)>>1;if(ql<=M) res+=Query(lc,L,M);if(qr>M) res+=Query(rc,M+1,R);return res;}
}seg;
struct qs{int opt,l,r,v,id,k;}q[N];
int n,m;int ans[N];
int cmp(qs a,qs b){return a.k==b.k?a.id<b.id:a.k<b.k;}
void solve(int L,int R,int l,int r){if(l>r) return;if(L==R){for(int i=l;i<=r;i++)if(q[i].opt==2) ans[q[i].id]=L;return;}seg.init();int M=(L+R)>>1,t=l-1,s;for(int i=l;i<=r;i++){if(q[i].opt==1){if(q[i].v>M){done;seg.Add(1,1,n);q[i].k=1;}else{t++,q[i].k=0;}}else{done;s=seg.Query(1,1,n);if(q[i].v<=s) q[i].k=1;else t++,q[i].k=0,q[i].v-=s;}}sort(q+l,q+r+1,cmp);solve(L,M,l,t);solve(M+1,R,t+1,r);
}
inline int in(int x=0,char ch=getchar()){while(ch>'9'||ch<'0') ch=getchar();while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();return x;
}
int main(){n=in(),m=in();for(int i=1;i<=m;i++){q[i].opt=in(),q[i].l=in(),q[i].r=in(),q[i].v=in(),q[i].id=i;}memset(ans,-1,sizeof(ans));solve(0,n,1,m);for(int i=1;i<=m;i++) if(ans[i]!=-1) printf("%d\n",ans[i]);return 0;
} 

BZOJ_P3110 [ZJOI2013]K大数查询(线段树+整体二分)相关推荐

  1. bzoj 3110: [Zjoi2013]K大数查询(树套树)

    树套树: 本质:一棵树的每个节点套着另一棵树 通常时间复杂度:O(nlog²n) 空间复杂度:因为树的大小是nlogn,而每个节点又有一棵nlogn的树,所以最大空间复杂度为O(n²log²) 但事实 ...

  2. bzoj3110: [Zjoi2013]K大数查询 【树套树,标记永久化】

    //========================== 蒟蒻Macaulish:http://www.cnblogs.com/Macaulish/  转载要声明! //=============== ...

  3. P3332 [ZJOI2013]K大数查询(整体二分做法)

    P3332 [ZJOI2013]K大数查询 题意: 题解: 利用整体二分来做,这个题和P3834 [模板]可持久化线段树 2的区别在于本题的修改是区间修改,所以将里面的树状数组改成线段树就行,区间修改 ...

  4. 洛谷 P3332 [ZJOI2013]K大数查询 解题报告

    P3332 [ZJOI2013]K大数查询 题目描述 有\(N\)个位置,\(M\)个操作.操作有两种,每次操作如果是\(\tt{1\ a\ b\ c}\)的形式表示在第\(a\)个位置到第\(b\) ...

  5. BZOJ3110: [Zjoi2013]K大数查询

    BZOJ3110: [Zjoi2013]K大数查询 Description 有N个位置,M个操作. 操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c 如 ...

  6. bzoj3110 [Zjoi2013]K大数查询

    3110: [Zjoi2013]K大数查询 Time Limit: 20 Sec  Memory Limit: 512 MB Submit: 10703  Solved: 3209 [Submit][ ...

  7. 3110: [Zjoi2013]K大数查询

    3110: [Zjoi2013]K大数查询 https://lydsy.com/JudgeOnline/problem.php?id=3110 分析: 整体二分+线段树. 两种操作:区间加入一个数,区 ...

  8. [BZOJ3110] [Zjoi2013]K大数查询

    3110: [Zjoi2013]K大数查询 Time Limit: 20 Sec  Memory Limit: 512 MB Submit: 9208  Solved: 2737 [Submit][S ...

  9. P3332 [ZJOI2013]K大数查询【整体二分】或【树套树】

    传送门 给定一个长度为NNN的可重集合 支持修改,离线 求区间可重集合的并集第K大 这里介绍两种方法[树套树]和 [整体二分] 这里还有个单点修改,有点类似的 P2617 Dynamic Rankin ...

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

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

最新文章

  1. 预加载显示图片的艺术
  2. C#-利用ZPL语言完毕条形码的生成和打印
  3. python2clock_控制fps的时钟Clock类源码
  4. android+图标+i_explore+无背景,Android Studio中Android Device Monitor中的File Explore不显示文...
  5. LeetCode 1940. 排序数组之间的最长公共子序列(二分查找)
  6. Spring2..5整合Ehacahe
  7. JS延迟加载百度分享代码,提高网页速度
  8. ComboBox控件值对类
  9. webservice 调用错误
  10. Flink Remote Shuffle 开源:面向流批一体与云原生的 Shuffle 服务
  11. 数据库实验四 视图实验
  12. 【FlinkX】两个issue分析:reader和writer的通道数不一致+获取JobId
  13. nii、npz、npy、dcm、mhd 的数据互转处理,及多目标分割处理汇总
  14. 前端学习图谱与新奇趣玩之前端Q直播回顾
  15. VC实现:bmp转jpg、jpg转bmp、截屏保存jpg
  16. 第四章:Android灯光系统(4)-电池灯
  17. 美丽苏大,清华博士,年轻硕导,招收研究生了!
  18. 亚马逊测评提升销量有什么好办法,分享6点技巧
  19. 植树节,送 25 本书福利一下
  20. 【教学类-12-02】20221105《连连看12*4-分栏4-不重复24个)(小班主题《白天与黑夜》)

热门文章

  1. Java的BIO和NIO很难懂?用代码实践给你看,再不懂我转行!
  2. 最简单最快速csv超大文件入库并统计Top5
  3. 羞羞的报告:2020年轻人性爱数据报告。
  4. Vue使用Echarts控件实现图表设计
  5. 【树莓派】挂载移动硬盘 使用transmission 刷pt站
  6. ubuntu18之wine
  7. 陈强教授《机器学习及R应用》课程第十一章作业
  8. 数字化时代,银行如何建设管理小程序平台促进线上金融业务发展?
  9. U盘文件夹变成.exe文件的解决方法
  10. 使用Graphics2D给报警图片画框和提示信息