[BZOJ3110][Zjoi2013]K大数查询
3110: [Zjoi2013]K大数查询
Time Limit: 20 Sec Memory Limit: 512 MB Submit: 9354 Solved: 2762 [Submit][Status][Discuss]Description
有N个位置,M个操作。操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c 如果是2 a b c形式,表示询问从第a个位置到第b个位置,第C大的数是多少。
Input
第一行N,M 接下来M行,每行形如1 a b c或2 a b c
Output
输出每个询问的结果
Sample Input
2 5
1 1 2 1
1 1 2 2
2 1 1 2
2 1 1 1
2 1 2 3
1 1 2 1
1 1 2 2
2 1 1 2
2 1 1 1
2 1 2 3
Sample Output
1
2
1
2
1
HINT
【样例说明】
第一个操作 后位置 1 的数只有 1 , 位置 2 的数也只有 1 。 第二个操作 后位置 1
的数有 1 、 2 ,位置 2 的数也有 1 、 2 。 第三次询问 位置 1 到位置 1 第 2 大的数 是
1 。 第四次询问 位置 1 到位置 1 第 1 大的数是 2 。 第五次询问 位置 1 到位置 2 第 3
大的数是 1 。
N,M<=50000,N,M<=50000
a<=b<=N
1操作中abs(c)<=N
2操作中c<=Maxlongint
整体二分
注意是第$K$大而不是第$K$小
数据有负数要离散化
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; char buf[10000000], *ptr = buf - 1; inline int readint(){ int n = 0; bool flag = false; while(*++ptr < '0' || *ptr > '9') if(*ptr == '-') flag = true; while(*ptr <= '9' && *ptr >= '0') n = (n << 1) + (n << 3) + (*ptr++ & 15); return flag ? -n : n; } typedef long long LL; const int maxn = 50000 + 10, maxm = 50000 + 10; int n, m; int num[maxm], ref[maxm], num_cnt; struct Bit{ LL c1[maxn], c2[maxn]; Bit(){ memset(c1, 0, sizeof(c1)); memset(c2, 0, sizeof(c2)); } void Update(const int &pos, const LL &v1){ LL v2 = (pos - 1) * v1; for(int i = pos; i <= n; i += i & -i){ c1[i] += v1; c2[i] += v2; } } LL Query(const int &pos){ LL s1 = 0, s2 = 0; for(int i = pos; i; i -= i & -i){ s1 += c1[i]; s2 += c2[i]; } return pos * s1 - s2; } }bit; inline void Update(const int &l, const int &r, const LL &val){ bit.Update(l, val); bit.Update(r + 1, -val); } inline LL Query(const int &l, const int &r){ return bit.Query(r) - bit.Query(l - 1); } struct Que{ int l, r, id; LL v; Que(){} Que(int _l ,int _r, LL _v, int _id): l(_l), r(_r), v(_v), id(_id){} }q[maxm]; bool mark[maxm]; int f[maxm], g[maxm]; int ans[maxm], ans_cnt = 0; void solve(int ql, int qr, int vl, int vr){ if(ql > qr) return; if(vl == vr){ for(int i = ql; i <= qr; i++) ans[q[f[i]].id] = vl; return; } int mid = vl + vr + 1 >> 1, cnt = 0; LL t; for(int i = ql; i <= qr; i++){ if(!q[f[i]].id){ if(q[f[i]].v >= mid){ Update(q[f[i]].l, q[f[i]].r, 1); mark[i] = true; cnt++; } else mark[i] = false; } else{ t = Query(q[f[i]].l, q[f[i]].r); if(t < q[f[i]].v){ mark[i] = false; q[f[i]].v -= t; } else{ mark[i] = true; cnt++; } } } int ll = ql, rr = ql + cnt; for(int i = ql; i <= qr; i++) if(mark[i]){ g[ll++] = f[i]; if(!q[f[i]].id) Update(q[f[i]].l, q[f[i]].r, -1); } else g[rr++] = f[i]; for(int i = ql; i <= qr; i++) f[i] = g[i]; solve(ql, ll - 1, mid, vr); solve(ll, qr, vl, mid - 1); } int main(){ FILE* fin_handle = fopen("in.txt", "r"); buf[fread(buf, sizeof(char), sizeof(buf), fin_handle)] = 0; freopen("out.txt", "w", stdout); n = readint(); m = readint(); for(int opt, a, b, c, i = 1; i <= m; i++){ opt = readint(); a = readint(); b = readint(); c = readint(); if(opt == 1){ q[i] = Que(a, b, (LL)c, 0); num[++num_cnt] = c; } else q[i] = Que(a, b, (LL)c, ++ans_cnt); } sort(num + 1, num + num_cnt + 1); num_cnt = unique(num + 1, num + num_cnt + 1) - (num + 1); for(int t, i = 1; i <= m; i++) if(!q[i].id){ t = lower_bound(num + 1, num + num_cnt + 1, q[i].v) - num; ref[t] = q[i].v; q[i].v = t; } for(int i = 1; i <= m; i++) f[i] = i; solve(1, m, 1, num[num_cnt]); for(int i = 1; i <= ans_cnt; i++) printf("%d\n", ref[ans[i]]); return 0; }