bzoj 3110

来源:互联网 发布:ubuntu 16.04 安装完 编辑:程序博客网 时间:2024/05/22 07:59

线段树套线段树,挺不错的一道数据结构题。


先读入所有询问并离散化,然后在外层建 权值线段树

权值线段树的每个结点建一棵 维护区间和 的线段树。

直接建树空间 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 Rvoid 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;}
0 0
原创粉丝点击