ZOJ

纠结了好久的一道题,以前是用线段树套平衡树二分做的,感觉时间复杂度和分块差不多了。。。

终于用BIT套函数式线段树了过了,120ms就是快,此题主要是卡内存。

假设离散后有ns个不同的值,递归层数是log2(ns)左右,nlog(ns),主席树是前缀区间,BIT保存修改的值是mlog2(ns)log2(ns)。

虽然这个算出来还是会爆,但是实际上会有一些结点复用,具体设置多少请相信玄学。(2e6左右)

ZOJ的Node*计算内存似乎有问题,必须用int

/*********************************************************
*            ------------------                          *
*   author AbyssFish                                     *
**********************************************************/
#include<cstdio>
#include<iostream>
#include<cstring>
#include<vector>
#include<algorithm>
#include<cmath>
using namespace std;
//#pragma pack(4)

const int MAX_N = 5e4+3;
const int MAX_M = 1e4+3;
const int MAX_NM = MAX_N+MAX_M;
const int MAX_D = 16;
const int MAX_ND = 0xac*MAX_M+0x42fed;//MAX_D*MAX_N+MAX_M*MAX_D*MAX_D;


int b[MAX_NM];
int mp_a[MAX_NM];

int ns, n_;

int N, M;

struct Cmd
{
    int i, j, k;
}qus[MAX_M];

struct Node
{
    int lc, rc;
    int s;
}p[MAX_ND];

int root[MAX_N];
int cnt;

#define lsn p[o].lc,l,md
#define rsn p[o].rc,md+1,r

void build(int x,int &o,int l = 1, int r = ns)
{
    p[++cnt] = p[o];
    o = cnt;
    p[o].s++;
    if(r > l){
        int md = (l+r)>>1;
        if(x <= md) build(x,lsn);
        else build(x,rsn);
    }
}

int BIT[MAX_N];

void inst(int x, int d, int &o, int l = 1, int r = ns)
{
    if(o == 0){
        p[++cnt] = p[o];
        o = cnt;
    }
    p[o].s += d;
    if(l < r){
        int md = (l+r)>>1;
        if(x<=md) inst(x,d,lsn);
        else inst(x,d,rsn);
    }

}

#define lowbit(x) ((x)&(-x))

void modify_bit(int pos, int x, int d)
{
    while(pos <= N){
        inst(x,d,BIT[pos]);
        pos += lowbit(pos);
    }
}

typedef vector<int> Prefix;

void prefix_bit(int pos, Prefix &res)
{
    res.clear();
    while(pos > 0){
        res.push_back(BIT[pos]);
        pos -= lowbit(pos);
    }
}


inline int cal_lft(Prefix &pfx)
{
    int re = 0;
    for(int i = pfx.size()-1; i >= 0; i--){
        re += p[p[pfx[i]].lc].s;
    }
    return re;
}

#define dump(pfx,ch)
for(i = pfx.size()-1; i >= 0; i--){
    pfx[i] = p[pfx[i]].ch;
}

Prefix X, Y;

int qkth(int k,int l = 1, int r = ns)
{
    if(l == r) return mp_a[l];
    else {
        int l_cnt = cal_lft(Y)-cal_lft(X);
        int md = (l+r)>>1, i;
        if(k <= l_cnt){
            dump(X,lc)
            dump(Y,lc)
            return qkth(k,l,md);
        }
        else {
            dump(X,rc)
            dump(Y,rc)
            return qkth(k-l_cnt,md+1,r);
        }
    }

}



void solve()
{
    cnt = 0;
    memset(BIT+1,0,sizeof(int)*N);
    int i;
    for(i = 1; i <= N; i++){
        root[i] = root[i-1];
        build(b[i], root[i]);
    }

    for(i = 0; i < M; i++){
        if(qus[i].j < 0){
            int pos = qus[i].i;
            modify_bit(pos,b[pos],-1);
            modify_bit(pos,b[pos] = b[qus[i].k],1);
        }
        else {
            int L = qus[i].i-1, R = qus[i].j;
            prefix_bit(L,X);
            prefix_bit(R,Y);
            X.push_back(root[L]);
            Y.push_back(root[R]);
            printf("%d
",qkth(qus[i].k));
        }
    }
}

int * const a = (int *)(p+2);
int * const r = a + MAX_NM;


void init()
{
    scanf("%d%d",&N,&M);
    for(int i = 1; i <= N; i++){
        scanf("%d",a+i);
        r[i] = i;
    }

    n_ = N;
    char ch[3];
    for(int i = 0; i < M; i++){
        scanf("%s",ch);
        if(*ch == 'Q') {
            scanf("%d%d%d",&qus[i].i,&qus[i].j,&qus[i].k);
        }
        else {
            qus[i].k = ++n_;
            r[n_] = n_;
            scanf("%d%d",&qus[i].i,a+n_);
            qus[i].j = -1;
        }
    }

    sort(r+1,r+n_+1,[](int i,int j){ return a[i]<a[j]; });
    mp_a[b[r[1]] = ns = 1] = a[r[1]];
    for(int i = 2; i <= n_; i++) {
        int k = r[i];
        if(a[k] != a[r[i-1]]){
            mp_a[b[k] = ++ns] = a[k];
        }
        else {
            b[k] = ns;
        }
    }
}



//#define LOCAL
int main()
{
#ifdef LOCAL
    freopen("in.txt","r",stdin);
#endif
    //cout<<ceil(log2(MAX_N+MAX_M))+1;
    //cout<<sizeof(Node*)<<endl;
    //cout<<MAX_ND<<endl;
   // cout<<MAX_ND*sizeof(Node)+(MAX_NM)*16+MAX_M*12+MAX_N*8;
   // cout<<sizeof(a)+sizeof(root)+sizeof(meo)+sizeof(qus)+sizeof(BIT)<<endl;//sizeof(b)+sizeof(mp_a)+sizeof(r)
    p[0] = {0,0,0};
    X.reserve(MAX_D+2);
    Y.reserve(MAX_D+2);

    int T; scanf("%d",&T);
    while(T--){
        init();
        solve();
    }
    return 0;
}
原文地址:https://www.cnblogs.com/jerryRey/p/5008876.html