纠结了好久的一道题,以前是用线段树套平衡树二分做的,感觉时间复杂度和分块差不多了。。。
终于用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; }