线段树套权值线段树 50pts Runtime Error
查看原帖
线段树套权值线段树 50pts Runtime Error
387961
rickyxrc楼主2023/10/26 11:11

空间开大会MLE,开小会RE。

// Problem: P2617 Dynamic Rankings
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P2617
// Memory Limit: 512 MB
// Time Limit: 3000 ms

#include<stdio.h>

bool ed;
const int maxn = 3.2e7+7;
const int minv = 0;
const int maxv = 1e9+7;
// const int maxv = 1000000027;

namespace vseg {
    struct Node {
        int count, sum, l, r;
    } tree[maxn];

    int cnt = 1;
    int newnode() { return ++cnt; }

    inline void update(int index) { tree[index].sum = tree[index].count + tree[tree[index].l].sum + tree[tree[index].r].sum; }

    void assert_val(bool val, char* failed) { if(not val) printf("%s FAILED.\n", failed); }

    void add(int index, int l, int r, int ind, int v) {
        if(l == r){
            assert_val(l==ind, "add::final_position");
            tree[index].count+=v, tree[index].sum+=v;
            return;
        }
        int mid = (l+r)>>1;
        if(ind <= mid) {
            if(not tree[index].l)
                tree[index].l = newnode();
            add(tree[index].l, l, mid, ind, v);
        }
        else {
            if(not tree[index].r)
                tree[index].r = newnode();
            add(tree[index].r, mid+1, r, ind, v);
        }
        update(index);
    }

    int rank(int index, int l, int r, int remain){
        if(l == r)
            return l;
        int mid = (l+r)>>1;
        if(tree[index].l and tree[index].r){
            if(remain-tree[tree[index].l].sum > 0)
                return rank(tree[index].r, mid+1, r, remain-tree[tree[index].l].sum);
            else
                return rank(tree[index].l, l, mid, remain);
            return 0;
        }
        else
            if(tree[index].l)
                return rank(tree[index].l, l, mid, remain);
            else
                return rank(tree[index].r, mid+1, r, remain);
    }
    
    int sum(int index, int l, int r, int ql, int qr){
        if(ql <= l and r <= qr)
            return tree[index].sum;
        if(l > qr or r < ql)
            return 0;
        int mid = (l+r)>>1, res = 0;
        if(tree[index].l)
            res += sum(tree[index].l, l, mid, ql, qr);
        if(tree[index].r)
            res += sum(tree[index].r, mid+1, r, ql, qr);
        return res;
    }
}

struct segt {
    int root;
    segt() { root = vseg::newnode(); }
    inline void add(int x) { vseg::add(root, minv, maxv, x, 1); }
    inline void rem(int x) { vseg::add(root, minv, maxv, x, -1); }
    inline int rank(int x) { return vseg::sum (root, minv, maxv, minv, x-1) + 1; }
    inline int kth (int x) { return vseg::rank(root, minv, maxv, x); }
    inline int pre (int x) { return vseg::rank(root, minv, maxv, vseg::sum(1, minv, maxv, minv, x-1)); }
    inline int nxt (int x) { return vseg::rank(root, minv, maxv, vseg::sum(1, minv, maxv, minv, x) + 1); }
    inline int size(int x) { return vseg::tree[root].sum; }
};

const int tmaxn = 4.1e5;

int li[tmaxn];
segt tree[tmaxn];

void build(int index, int l, int r){
    // printf("%d, [%d, %d]\n", index, l, r);
    for(int i=l; i<=r; i++){
        // printf("%d add %d\n", index, li[i]);
        tree[index].add(li[i]);
    }
    if(l==r)
        return;
    int mid = (l+r)>>1;
    build(index<<1  , l, mid);
    build(index<<1|1, mid+1, r);
}

void modify(int index, int l, int r, int pos, int pre, int v){
    if(l <= pos and pos <= r)
        // printf("%d modify %d %d\n", index, pre, v),
        tree[index].rem(pre),
        tree[index].add(v);
    if(l == r) return;
    int mid = (l+r)>>1;
    modify(index<<1  , l, mid, pos, pre, v);
    modify(index<<1|1, mid+1, r, pos, pre, v);
}

int rank(int index, int l, int r, int ql, int qr, int k){
    if(l > qr or r < ql)
        return 0;
    if(ql <= l and r <= qr)
        return tree[index].rank(k)-1;
    int mid = (l+r) >> 1;
    return rank(index<<1, l, mid, ql, qr, k) + rank(index<<1|1, mid+1, r, ql, qr, k);
}

int n, m, u, v, w;
int queryk(int ql, int qr, int k){
    int l = minv, r = maxv;
    while(r-l>1){
        int mid = (l+r)>>1;
        // printf("%d, %d val = %d, rank = %d\n", l, r, mid, rank(1, 1, n, ql, qr, mid) + 1);
        if(rank(1, 1, n, ql, qr, mid) + 1 <= k)
            l = mid;
        else
            r = mid;
    }
    for(int i=r;i>=l;i--)
        if(rank(1, 1, n, ql, qr, i)+1 <= k)
            return i;
    printf("WHAR???\n");
}
bool bg;

char ch;

int main(){
#ifdef debug_rickyxrc
    fprintf(stderr, "Mem usage : %.4lf KB\n", (&ed-&bg) /1024.0);
    fprintf(stderr, "Mem usage : %.4lf MB\n", (&ed-&bg) /1024.0/1024.0);
#endif
    scanf("%d%d", &n, &m);
    for(int i=1;i<=n;i++)
        scanf("%d", li+i);
    build(1, 1, n);
    // printf("%d\n", rank(1, 1, n, 1, 4, 9) + 1);
    for(int i=1;i<=m;i++){
        do
            ch=getchar();
        while(ch!='Q' and ch!='C');
        if(ch == 'Q')
            scanf("%d%d%d", &u, &v, &w),
            printf("%d\n", queryk(u, v, w));
        else
            scanf("%d%d", &u, &v),
            modify(1, 1, n, u, li[u], v),
            li[u] = v;
    }
    return 0;
}

2023/10/26 11:11
加载中...