原题地址:http://csustacm.com:4803/problem/1015
思路:由于k很小,所以每次用线段树维护前k大的数字就行了.
#include <bits/stdc++.h>
#include <cmath>
#define eps 1e-8
#define INF 0x3f3f3f3f
#define PI acos(-1)
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define CLR(x,y) memset((x),y,sizeof(x))
#define fuck(x) cout<<"["<<"x = "<<(x)<<"] "
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int seed = 131;
const int maxn = 5e5 + 5;
const int mod = 998244353;
int n, m, k;
//bool cmp(int a,int b) {
//return a>b;
//}
struct node {
int v[5];
node() {
CLR(v, 0);
}
node operator +(const node &a)const {//重载结构体 '+',便于后面操作
int t[20];
CLR(t, 0);
node tmp;
int top = 0;
for(int i = 0; i < k; i++) t[top++] = v[i];//合并两个结构体,求前K大数
for(int i = 0; i < k; i++) t[top++] = a.v[i];
sort(t, t + top, greater<int>());
for(int i = 0; i < k; i++) tmp.v[i] = t[i];
return tmp;
}
} e[maxn<<2];
void build(int l, int r, int rt) {//建树初始化
for(int i = 0; i < k; i++) e[rt].v[i] = 0;
if(l == r) {
scanf("%d", &e[rt].v[0]);
return ;
}
int mid = (l + r) >> 1;
build(lson);
build(rson);
e[rt] = e[rt << 1] + e[rt << 1 | 1];
}
void updata(int p, int v, int l, int r, int rt) {
if(l == r) {//更新最下面的叶子节点,单点更新
e[rt].v[0] = v;
return ;
}
int mid = (l + r) >> 1;
if(mid >= p) updata(p, v, lson);
else updata(p, v, rson);
e[rt] = e[rt << 1] + e[rt << 1 | 1];
}
node query(int L, int R, int l, int r, int rt) {//区间查询
if(L <= l && R >= r) return e[rt];
int mid = (l + r) / 2;
node tmp;
if(mid >= L) tmp = tmp + query(L, R, lson);
if(mid < R) tmp = tmp + query(L, R, rson);
return tmp;
}
int main() {
while(~scanf("%d%d%d", &n, &m, &k)) {
build(1, n, 1);
while(m--) {
int op, p, v;
scanf("%d%d%d", &op, &p, &v);
if(op == 1) {
updata(p, v, 1, n, 1);
} else {
node tmp = query(p, v, 1, n, 1);
for(int i = 0; i < k; i++) printf("%d%c", tmp.v[i], i == k - 1 ? '\n' : ' ');
}
}
}
return 0;
}