记录编号 443917 评测结果 AAAAAAAAAA
题目名称 [ZJOI 2013] K大数查询 最终得分 100
用户昵称 GravatarHeHe 是否通过 通过
代码语言 C++ 运行时间 10.296 s
提交时间 2017-09-01 19:44:51 内存使用 1.56 MiB
显示代码纯文本
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;

typedef long long LL;

inline char getc(void) { 
    static char buf[1 << 18], *fs, *ft;
    return (fs == ft && (ft = (fs = buf) + fread(buf, 1, 1 << 18, stdin)), fs == ft) ? EOF : *fs++;
}

inline int read(void) { 
    register int res = 0;
    register char tmp = getc(), f = 1;
    while(!isgraph(tmp)) tmp = getc();
    if(tmp == '-') f = -1, tmp = getc();
    while(isdigit(tmp))
        res = ((res + (res << 2)) << 1) + (tmp ^ 0x30),
        tmp = getc();
    return res * f;
}

char ops[1 << 20], *opt = ops, *const opt_end = ops + (1 << 20);

inline void write_all(void) { 
    fwrite(ops, 1, opt - ops, stdout);
    opt = ops; return ;
}

inline void write(LL x) { 
    static char *p = new char[20]();
    if(x < 0) { 
        *(opt++) = '-'; 
        if(opt == opt_end) write_all();
        x = -x;
    }
    do{ 
        *(++p) = (x % 10) | 0x30;
        x /= 10;
    }while(x);
    while(*p) { 
        *(opt++) = *(p--);
        if(opt == opt_end) write_all();
    }
    *(opt++) = '\n';
    if(opt == opt_end) write_all();
    return ;
}

struct NODE2{ //区间线段树节点
    unsigned cnt, tag;
    NODE2 *ls, *rs;
    NODE2() { ls = rs = NULL; cnt = 0;}
};

struct NODE1{ //权值线段树节点
    NODE2 *root;
    NODE1 *ls, *rs;
    NODE1() { root = NULL; ls = rs = NULL;}
};

void Build(NODE1 *&node, int L, int R);
inline void Pushdown(NODE2 *node, int L, int R);
void Insert(NODE1 *&node, int l, int r, int k, int L, int R);
int Query(NODE1 *node, int l, int r, unsigned k, int L, int R);

int N, M, a, b, c;
unsigned d;
NODE1 *root;

int main() { 
#ifndef LOCAL
    freopen("zjoi13_sequence.in", "r", stdin);
    freopen("zjoi13_sequence.out", "w", stdout);
#endif
    N = read(), M = read();
    Build(root, -N, N);
    while(M--) 
        if(read() == 1) 
            a = read(), b = read(), c = read(),
            Insert(root, a, b, c, -N, N);
        else a = read(), b = read(), c = read(),
            write(Query(root, a, b, c, -N, N));
    write_all();
    return 0;
}
//建立权值线段树
void Build(NODE1 *&node, int L, int R) { 
    node = new NODE1();
    if(L ^ R) { 
        int M = (L + R) >> 1;
        Build(node->ls, L, M);
        Build(node->rs, M + 1, R);
    }
    return ;
}
//下方lazy tag并动态开点
inline void Pushdown(NODE2 *node, int L, int R) { 
    if(L == R || !node->tag) return ;
    int M = (L + R) >> 1, Len;
    if(!node->ls) node->ls = new NODE2();Len = M - L + 1;
    node->ls->tag += node->tag; node->ls->cnt += node->tag * Len;
    if(!node->rs) node->rs = new NODE2();Len = R - M;
    node->rs->tag += node->tag; node->rs->cnt += node->tag * Len;
    node->tag = 0; return ;
}
//插入区间线段树
void Insert(NODE2 *&node, int l, int r, int L, int R) { 
    if(!node) node = new NODE2();
    Pushdown(node, L, R);
    if(l <= L && R <= r) ++node->tag, node->cnt += (R - L + 1);
    else { 
        int M = (L + R) >> 1;
        if(l <= M) Insert(node->ls, l, r, L, M);
        if(M < r) Insert(node->rs, l, r, M + 1, R);
        node->cnt = 0;
        if(node->ls) node->cnt += node->ls->cnt;
        if(node->rs) node->cnt += node->rs->cnt;
    }
    return ;
}
//插入权值线段树
void Insert(NODE1 *&node, int l, int r, int k, int L, int R) { 
    Insert(node->root, l, r, 1, N); 
    if(L == R) return ;
    int M = (L + R) >> 1;
    if(k <= M) Insert(node->ls, l, r, k, L, M);
    else Insert(node->rs, l, r, k, M + 1, R);
    return ;
}
//查询数字个数
unsigned Query(NODE2 *node, int l, int r, int L, int R) { 
    if(!node) return 0;
    Pushdown(node, L, R);
    if(l <= L && R <= r) return node->cnt;
    int M = (L + R) >> 1; unsigned ret = 0;
    if(l <= M) ret += Query(node->ls, l, r, L, M);
    if(M < r) ret += Query(node->rs, l, r, M + 1, R);
    return ret;
}
//查询从l到r之间第k大
int Query(NODE1 *node, int l, int r, unsigned k, int L, int R) { 
    if(L == R) return L;
    unsigned tmp = Query(node->rs->root, l, r, 1, N);
    int M = (L + R) >> 1;
    if(k <= tmp) return Query(node->rs, l, r, k, M + 1, R);
    else return Query(node->ls, l, r, k - tmp, L, M);
}