[ZJOI 2013] K大数查询
Posted evenbao
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[ZJOI 2013] K大数查询相关的知识,希望对你有一定的参考价值。
[题目链接]
https://www.lydsy.com/JudgeOnline/problem.php?id=3110
[算法]
整体二分 + 线段树
时间复杂度 : O(NlogN ^ 2)
[代码]
#include<bits/stdc++.h> using namespace std; #define MAXN 500010 typedef long long ll; typedef long double ld; struct query { int type , a , b; ll c; int id; } q[MAXN]; int n , m; int ans[MAXN]; struct Segment_Tree { ll cnt[MAXN << 4] , tag[MAXN << 4]; Segment_Tree() { memset(cnt , 0 , sizeof(cnt)); } inline void pushdown(int index , int l , int r) { int mid = (l + r) >> 1; cnt[index << 1] += (mid - l + 1) * tag[index]; cnt[index << 1 | 1] += (r - mid) * tag[index]; tag[index << 1] += tag[index]; tag[index << 1 | 1] += tag[index]; tag[index] = 0; } inline void update(int index) { cnt[index] = cnt[index << 1] + cnt[index << 1 | 1]; } inline void modify(int now , int l , int r , int ql , int qr , int value) { if (l == ql && r == qr) { cnt[now] += 1ll * value * (qr - ql + 1); tag[now] += 1ll * value; return; } pushdown(now , l , r); int mid = (l + r) >> 1; if (mid >= qr) modify(now << 1 , l , mid , ql , qr , value); else if (mid + 1 <= ql) modify(now << 1 | 1 , mid + 1 , r , ql , qr , value); else { modify(now << 1 , l , mid , ql , mid , value); modify(now << 1 | 1 , mid + 1 , r , mid + 1 , qr , value); } update(now); } inline ll query(int now , int l , int r , int ql , int qr) { if (l == ql && r == qr) return cnt[now]; pushdown(now , l , r); int mid = (l + r) >> 1; if (mid >= qr) return query(now << 1 , l , mid , ql , qr); else if (mid + 1 <= ql) return query(now << 1 | 1 , mid + 1 , r , ql , qr); else return query(now << 1 , l , mid , ql , mid) + query(now << 1 | 1 , mid + 1 , r , mid + 1 , qr); } } SGT; template <typename T> inline void chkmin(T &x , T y) { x = min(x , y); } template <typename T> inline void chkmax(T &x , T y) { x = max(x , y); } template <typename T> inline void read(T &x) { T f = 1; x = 0; char c = getchar(); for (; !isdigit(c); c = getchar()) if (c == ‘-‘) f = -f; for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - ‘0‘; x *= f; } inline void divide(int l , int r , int L , int R) { static query tl[MAXN] , tr[MAXN]; int mid = (l + r) >> 1; if (L > R) return; if (l == r) { for (int i = L; i <= R; i++) if (q[i].type == 2) ans[q[i].id] = mid; return; } else { int pl = 0 , pr = 0; for (int i = L; i <= R; i++) { if (q[i].type == 1) { if (q[i].c > mid) { tr[++pr] = q[i]; SGT.modify(1 , 1 , n , q[i].a , q[i].b , 1); } else tl[++pl] = q[i]; } else { if (SGT.query(1 , 1 , n , q[i].a , q[i].b) >= q[i].c) tr[++pr] = q[i]; else { q[i].c -= SGT.query(1 , 1 , n , q[i].a , q[i].b); tl[++pl] = q[i]; } } } for (int i = L; i <= R; i++) if (q[i].type == 1 && q[i].c > mid) SGT.modify(1 , 1 , n , q[i].a , q[i].b , -1); for (int i = L; i <= L + pl - 1; i++) q[i] = tl[i - L + 1]; for (int i = L + pl; i <= R; i++) q[i] = tr[i - L - pl + 1]; divide(l , mid , L , L + pl - 1); divide(mid + 1 , r , L + pl , R); } } int main() { read(n); read(m); vector< int > que; for (int i = 1; i <= m; i++) { read(q[i].type); read(q[i].a); read(q[i].b); read(q[i].c); q[i].id = i; if (q[i].type == 2) que.push_back(i); } divide(-n , n , 1 , m); for (unsigned i = 0; i < que.size(); i++) printf("%d " , ans[que[i]]); return 0; }
以上是关于[ZJOI 2013] K大数查询的主要内容,如果未能解决你的问题,请参考以下文章
BZOJ3110 [ZJOI2013] K大数查询(加强数据)
bzoj 3110 [Zjoi2013]K大数查询 整体二分