您的位置:首页 > 其它

ZOJ - 2112 Dynamic Rankings(BIT套主席树)

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

终于用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\n",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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: