1. 程式人生 > >[ZJOI 2013] K大數查詢

[ZJOI 2013] K大數查詢

static names dig truct tree 鏈接 整體二分 modify php

[題目鏈接]

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\n" , ans[que[i]]); return 0; }

[ZJOI 2013] K大數查詢