您的位置:首页 > 其它

BZOJ 3110: [Zjoi2013]K大数查询

2015-09-06 09:59 316 查看

3110: [Zjoi2013]K大数查询

Time Limit: 20 Sec Memory Limit: 512 MB
Submit: 2276 Solved: 1021

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

Sample Output

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操作中abs(c)<=Maxlongint

解题:整体二分+树状数组改段求段

#include <bits/stdc++.h>
using namespace std;
const int maxn = 200010;
struct QU {
int x,y,k,id,cache;
} Q[maxn],A[maxn],B[maxn];
int c[2][maxn],ans[maxn];
void add(int *c,int i,int val) {
while(i < maxn) {
c[i] += val;
i += i&-i;
}
}
int sum(int *c,int i,int ret = 0) {
while(i > 0) {
ret += c[i];
i -= i&-i;
}
return ret;
}
void solve(int lt,int rt,int L,int R) {
if(lt > rt) return;
if(L == R) {
for(int i = lt; i <= rt; ++i)
if(Q[i].id > -1) ans[Q[i].id] = L;
return;
}
int mid = (L + R)>>1,a = 0,b = 0;
for(int i = lt; i <= rt; ++i) {
if(Q[i].id == -1) {
if(Q[i].k > mid) {
add(c[0],Q[i].x,1);
add(c[0],Q[i].y+1,-1);
add(c[1],Q[i].x,Q[i].x);
add(c[1],Q[i].y+1,-Q[i].y-1);
A[a++] = Q[i];
}else B[b++] = Q[i];
} else {
int tmp = (Q[i].y+1)*sum(c[0],Q[i].y) - sum(c[1],Q[i].y)
- (Q[i].x)*sum(c[0],Q[i].x-1) + sum(c[1],Q[i].x-1);
if(tmp + Q[i].cache >= Q[i].k) A[a++] = Q[i];
else {
Q[i].cache += tmp;
B[b++] = Q[i];
}
}
}
for(int i = lt; i <= rt; ++i) {
if(Q[i].id == -1 && Q[i].k > mid) {
add(c[0],Q[i].x,-1);
add(c[0],Q[i].y+1,1);
add(c[1],Q[i].x,-Q[i].x);
add(c[1],Q[i].y+1,Q[i].y+1);
}
}
for(int i = 0; i < b; ++i) Q[lt + i] = B[i];
for(int i = 0; i < a; ++i) Q[lt + b + i] = A[i];
solve(lt,lt+b-1,L,mid);
solve(lt+b,rt,mid+1,R);
}
int main() {
int n,m,op,ask = 0;
scanf("%d%d",&n,&m);
for(int i = 0; i < m; ++i) {
scanf("%d%d%d%d",&op,&Q[i].x,&Q[i].y,&Q[i].k);
if(op == 2) Q[i].id = ask++;
else Q[i].id = -1;
Q[i].cache = 0;
}
solve(0,m-1,-n,n);
for(int i = 0; i < ask; ++i) printf("%d\n",ans[i]);
return 0;
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: