3110: [Zjoi2013]K大数查询
3110: [Zjoi2013]K大数查询
https://lydsy.com/JudgeOnline/problem.php?id=3110
分析:
整体二分+线段树。
两种操作:区间加入一个数,区间询问第k大值。
如果只有一种操作,我们可以二分答案x,然后把大于x的都加入到线段树中去(区间[l,r]整体+1),然后查询这次询问的区间有多少数(区间[l,r]求和)。
多种操作的话整体二分就行了,注意到有时间顺序,所以可以按照时间顺序加入和查询。
注意一下要开longlong。
代码:
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 #include<iostream> 5 #include<cmath> 6 #include<cctype> 7 #include<set> 8 #include<queue> 9 #include<vector> 10 #include<map> 11 #define Root 1, n, 1 12 #define lson l, mid, rt << 1 13 #define rson mid + 1, r, rt << 1 | 1 14 using namespace std; 15 typedef long long LL; 16 17 inline int read() { 18 int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1; 19 for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f; 20 } 21 22 const int N = 50005; 23 24 int ans[N], n, m; 25 struct Que{ 26 int ty, l, r, v, id; 27 bool operator < (const Que &A) const { 28 return id < A.id; 29 } 30 }A[N], tl[N], tr[N]; 31 struct SegmentTree{ 32 LL sum[N << 2], tag[N << 2]; 33 void pushup(int rt) { sum[rt] = sum[rt << 1] + sum[rt << 1 | 1]; } 34 void pushdown(int rt,int len) { 35 sum[rt << 1] += 1ll * (len - len / 2) * tag[rt]; 36 sum[rt << 1 | 1] += 1ll * (len / 2) * tag[rt]; 37 tag[rt << 1] += tag[rt]; 38 tag[rt << 1 | 1] += tag[rt]; 39 tag[rt] = 0; 40 } 41 void update(int l,int r,int rt,int L,int R,int v) { 42 if (L <= l && r <= R) { 43 tag[rt] += v, sum[rt] += (r - l + 1) * v; return ; 44 } 45 if (tag[rt]) pushdown(rt, r - l + 1); 46 int mid = (l + r) >> 1; 47 if (L <= mid) update(lson, L, R, v); 48 if (R > mid) update(rson, L, R, v); 49 pushup(rt); 50 } 51 LL query(int l,int r,int rt,int L,int R) { 52 if (L <= l && r <= R) return sum[rt]; 53 if (tag[rt]) pushdown(rt, r - l + 1); 54 int mid = (l + r) >> 1; LL res = 0; 55 if (L <= mid) res += query(lson, L, R); 56 if (R > mid) res += query(rson, L, R); 57 return res; 58 } 59 }T; 60 61 void solve(int l,int r,int Head,int Tail) { 62 if (Head > Tail) return ; 63 if (l == r) { 64 for (int i = Head; i <= Tail; ++i) 65 if (A[i].ty == 2) ans[A[i].id] = l; 66 return ; 67 } 68 int mid = (l + r + 1) >> 1, cl = 0, cr = 0; 69 for (int i = Head; i <= Tail; ++i) { 70 if (A[i].ty == 1) { 71 if (A[i].v >= mid) T.update(Root, A[i].l, A[i].r, 1), tr[++cr] = A[i]; 72 else tl[++cl] = A[i]; 73 } 74 else { 75 LL t = T.query(Root, A[i].l, A[i].r); 76 if (t >= A[i].v) tr[++cr] = A[i]; 77 else A[i].v -= t, tl[++cl] = A[i]; 78 } 79 } 80 for (int i = Head; i <= Tail; ++i) if (A[i].ty == 1 && A[i].v >= mid) T.update(Root, A[i].l, A[i].r, -1); 81 for (int i = 1; i <= cl; ++i) A[i + Head - 1] = tl[i]; 82 for (int i = 1; i <= cr; ++i) A[i + Head + cl - 1] = tr[i]; 83 solve(l, mid - 1, Head, Head + cl - 1); 84 solve(mid, r, Head + cl, Tail); 85 } 86 int main() { 87 n = read(), m = read(); int Q = 0; 88 for (int i = 1; i <= m; ++i) { 89 A[i].ty = read(), A[i].l = read(), A[i].r = read(), A[i].v = read(), A[i].id = 0; 90 if (A[i].ty == 2) A[i].id = ++Q; 91 } 92 solve(0, n, 1, m); 93 for (int i = 1; i <= Q; ++i) printf("%d\n",ans[i]); 94 return 0; 95 }
转载于:https://www.cnblogs.com/mjtcn/p/10081790.html
3110: [Zjoi2013]K大数查询相关推荐
- bzoj 3110: [Zjoi2013]K大数查询(树套树)
树套树: 本质:一棵树的每个节点套着另一棵树 通常时间复杂度:O(nlog²n) 空间复杂度:因为树的大小是nlogn,而每个节点又有一棵nlogn的树,所以最大空间复杂度为O(n²log²) 但事实 ...
- bzoj:3110: [Zjoi2013]K大数查询
Description 有N个位置,M个操作.操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c 如果是2 a b c形式,表示询问从第a个位置到第b个位 ...
- [bzoj 3110] [ZJOI2013] K大数查询
题目链接: https://www.lydsy.com/JudgeOnline/problem.php?id=3110 题目: 有N个位置,M个操作.操作有两种,每次操作如果是: 1 a b c:表示 ...
- bzoj3110 [Zjoi2013]K大数查询
3110: [Zjoi2013]K大数查询 Time Limit: 20 Sec Memory Limit: 512 MB Submit: 10703 Solved: 3209 [Submit][ ...
- [BZOJ3110] [Zjoi2013]K大数查询
3110: [Zjoi2013]K大数查询 Time Limit: 20 Sec Memory Limit: 512 MB Submit: 9208 Solved: 2737 [Submit][S ...
- 洛谷 P3332 [ZJOI2013]K大数查询 解题报告
P3332 [ZJOI2013]K大数查询 题目描述 有\(N\)个位置,\(M\)个操作.操作有两种,每次操作如果是\(\tt{1\ a\ b\ c}\)的形式表示在第\(a\)个位置到第\(b\) ...
- BZOJ3110: [Zjoi2013]K大数查询
BZOJ3110: [Zjoi2013]K大数查询 Description 有N个位置,M个操作. 操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c 如 ...
- P3332 [ZJOI2013]K大数查询(整体二分做法)
P3332 [ZJOI2013]K大数查询 题意: 题解: 利用整体二分来做,这个题和P3834 [模板]可持久化线段树 2的区别在于本题的修改是区间修改,所以将里面的树状数组改成线段树就行,区间修改 ...
- bzoj3110: [Zjoi2013]K大数查询 【树套树,标记永久化】
//========================== 蒟蒻Macaulish:http://www.cnblogs.com/Macaulish/ 转载要声明! //=============== ...
最新文章
- 五子棋html游戏代码与算法介绍
- python交互窗口怎么才能不连着上一个程序_python实现启动一个外部程序,并且不阻塞当前进程...
- 解决Ubuntu无法进行SSH连接的问题(以及如何使用SSH)
- 对象属性之间的相互赋值
- 应对“反洗钱”,银丰新融反洗钱自主监测系统为机构保驾护航
- shell连接远程mongodb数据库
- FairMOT: On the Fairness of Detection and Re-Identification in Multiple Object Tracking 效果展示
- Srs之Clion编译
- 搭建Android的开发环境
- 2017服务器cpu性能排行,桌面CPU性能排行 CPU天梯图2017年7月最新版
- 搭窝---开篇语---爆笑语录
- @Value 注解用法
- 苏宁 OLAP 引擎发展之路
- 4.文本分类——textRNN模型
- 程序员常用工具网站汇总(一)
- 未能从程序集“mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089”中加载类型“System.Coll
- 不相信九江大桥事故专家鉴定的五大理由
- PyCharm 社区版(Community)能不能商用?
- python图片镜像反转
- 查找数组中的所有重复项