[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大数查询的主要内容,如果未能解决你的问题,请参考以下文章

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

BZOJ3110 [ZJOI2013] K大数查询(加强数据)

bzoj3110 [Zjoi2013]K大数查询

bzoj 3110 [Zjoi2013]K大数查询 整体二分

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

BZOJ 3110: [Zjoi2013]K大数查询 [树套树]