树分治 (线段树维护区间前k大)

原题地址: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;
}

猜你喜欢

转载自blog.csdn.net/yiqzq/article/details/81587657