bzoj 3110


線段樹套線段樹,挺不錯的一道數據結構題。


先讀入所有詢問並離散化,然後在外層建 權值線段樹

權值線段樹的每個結點建一棵 維護區間和 的線段樹。

直接建樹空間 O(N2) 肯定會MLE,所以先建出權值線段樹,再動態加點線段樹維護區間和即可。


時間複雜度O(logMlogNM)

空間複雜度O(M(logN)2)


學到了新姿勢,重載括號運算符:

int& operator [](int id)
    {
        return *(__arr + id);
    }

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <ctime>
#include <vector>
#include <utility>
#include <stack>
#include <queue>
#include <iostream>
#include <algorithm>

template<class Num>void read(Num &x)
{
    char c; int flag = 1;
    while((c = getchar()) < '0' || c > '9')
        if(c == '-') flag *= -1;
    x = c - '0';
    while((c = getchar()) >= '0' && c <= '9')
        x = (x<<3) + (x<<1) + (c-'0');
    x *= flag;
    return;
}
template<class Num>void write(Num x)
{
    if(x < 0) putchar('-'), x = -x;
    static char s[20];int sl = 0;
    while(x) s[sl++] = x%10 + '0',x /= 10;
    if(!sl) {putchar('0');return;}
    while(sl) putchar(s[--sl]);
}
struct vetor
{
#define begin() (__arr + 1)
#define end() (__arr + __len + 1)

    int *__arr, __len;

    void set(int size)
    {
        __len = 0, __arr = (int*)malloc(sizeof(int)*size);
    }
    void push_back(int x)
    {
        __arr[++__len] = x;
    }
    int size()
    {
        return __len;
    }
    void unique()
    {
        std::sort(begin(),end());
        __len = std::unique(begin(),end()) - begin();
    }
    int find(int x)
    {
        return std::lower_bound(begin(), end(), x)-begin()+1;
    }
    void erase()
    {
        __len = 0;
    }
    int& operator [](int id)
    {
        return *(__arr + id);
    }
#undef begin
#undef end
}bowl;
#define REP(__i,__start,__end) for(int __i = (__start); __i <= (__end); __i++)

const int maxm = 5e4 + 50, maxn = 5e4 + 50;
const int logM = 16, logN = logM, size = logM*(logN<<1)*maxm + (maxm << 2);

struct type_op
{
    int tp, a, b, c; 

    void init()
    {
        read(tp), read(a), read(b), read(c);
        if(tp == 1) bowl.push_back(c);
    }
}op[maxm];

int val[maxm << 2], lc[size], rc[size], cnt[size], addv[size];
int n, m, ind;

int pushdown(int si,int ll,int rr)
{
    int mid = ll + rr >> 1;

    if(!lc[si]) lc[si] = ++ind;
    if(!rc[si]) rc[si] = ++ind;

    cnt[lc[si]] += addv[si]*(mid - ll + 1);
    cnt[rc[si]] += addv[si]*(rr - mid);

    addv[lc[si]] += addv[si], addv[rc[si]] += addv[si], addv[si] = 0;   

    return mid;
}
void update(int si)
{
    cnt[si] = cnt[lc[si]] + cnt[rc[si]];
}
void insert(int l,int r,int ll,int rr,int si)
{
    if(l == ll && r == rr) cnt[si] += r - l + 1, addv[si] ++;
    else
    {
        int mid = pushdown(si, ll, rr);

        if(mid < l)
            insert(l, r, mid + 1, rr, rc[si]);
        else if(r <= mid)
            insert(l, r, ll, mid, lc[si]);
        else
        {
            insert(l, mid, ll, mid, lc[si]);
            insert(mid + 1, r, mid + 1, rr, rc[si]);
        }

        update(si);
    }
}

int query(int l,int r,int ll,int rr,int si)
{
    if(l == ll && r == rr) return cnt[si];
    else
    {
        int mid = pushdown(si, ll, rr);

        if(mid < l)
            return query(l, r, mid + 1, rr, rc[si]);
        else if(r <= mid)
            return query(l, r, ll, mid, lc[si]);
        else
            return query(l, mid, ll, mid, lc[si]) + query(mid + 1, r, mid + 1, rr, rc[si]);

        update(si);
    }
}
#define L(x) ((x)<<1)
#define R(x) ((x)<<1|1)

void build(int ll,int rr,int sv)
{
    val[sv] = ++ind;

    if(ll != rr) 
    {
        int mid = ll + rr >> 1;

        build(ll, mid, L(sv));
        build(mid + 1, rr, R(sv));
    }
}
void add(int l,int r,int v,int ll,int rr,int si)
{
    insert(l, r, 1, n, val[si]);

    if(ll != rr)
    {
        int mid = ll + rr >> 1;

        if(v <= mid) add(l, r, v, ll, mid, L(si));
        else add(l, r, v, mid + 1, rr, R(si));
    }           
}
int ask(int l,int r,int v,int ll,int rr,int si)
{
    if(ll == rr) return ll;

    int mid = ll + rr >> 1, rcnt;

    if((rcnt = query(l, r, 1, n, val[R(si)])) >= v)
        return ask(l, r, v, mid + 1, rr, R(si));
    else
        return ask(l, r, v - rcnt, ll, mid, L(si)); 
}
#undef L
#undef R

void init()
{
    bowl.set(maxm), read(n), read(m);

    REP(i, 1, m) op[i].init();
}
void prework()
{
    bowl.unique();

    REP(i, 1, m) if(op[i].tp == 1) op[i].c = bowl.find(op[i].c);

    build(1, bowl.size(), 1);
}
void solve()
{
    for(int i = 1; i <= m; i++)
    {
        if(op[i].tp == 1)
            add(op[i].a, op[i].b, op[i].c, 1, bowl.size(), 1);
        else
            write(bowl[ask(op[i].a, op[i].b, op[i].c, 1, bowl.size(), 1)]), puts("");
    }
}

int main()
{
#ifndef ONLINE_JUDGE
    freopen("3110.in","r",stdin);
    freopen("3110.out","w",stdout);
#endif

    init();

    prework();

    solve();

#ifndef ONLINE_JUDGE
    fclose(stdin);
    fclose(stdout);
#endif
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章