[FJOI2015]火星商店问题

[FJOI2015]火星商店问题


神仙线段树分治。。。不过我不会。

这题用线段树套可持久化Trie还是能写的。

常数有点大,洛谷垫底水平。

// luogu-judger-enable-o2
#include<bits/stdc++.h>
#define il inline
#define vd void
typedef long long ll;
il int gi(){
    int x=0,f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9'){
        if(ch=='-')f=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
    return x*f;
}
int rt[2000000],ch[10000000][2],tot[10000000];
int cnt,id;
il vd cp(int a,int b){ch[b][0]=ch[a][0],ch[b][1]=ch[a][1],tot[b]=tot[a];}
il vd Insert(int lst,int p){
    rt[++cnt]=++id;
    cp(rt[lst],rt[cnt]);
    int y=rt[cnt];
    for(int i=16;~i;--i){
        ++tot[y];
        int t=(p>>i)&1;
        cp(ch[y][t],++id);ch[y][t]=id;
        y=ch[y][t];
    }
    ++tot[y];
}
il int Query(int x,int y,int k){
    int ans=0;
    for(int i=16;~i;--i){
        int t=(k>>i)&1;
        if(tot[ch[y][!t]]!=tot[ch[x][!t]])ans+=1<<i,x=ch[x][!t],y=ch[y][!t];
        else x=ch[x][t],y=ch[y][t];
    }
    return ans;
}
std::vector<std::pair<int,int> >S[400001];
#define mid ((l+r)>>1)
#define ls (x<<1)
#define rs (x<<1|1)
typedef const int& ci;
il vd update(int x,int l,int r,ci p,ci d,ci T){
    Insert(S[x].back().first,d);
    S[x].push_back(std::make_pair(cnt,T));
    if(l==r)return;
    if(p<=mid)update(ls,l,mid,p,d,T);
    else update(rs,mid+1,r,p,d,T);
}
il int query(int x,int l,int r,ci L,ci R,ci k,ci d){
    if(L<=l&&r<=R){
        int LL=0,RR=S[x].size()-1;
        while(LL<RR){
            int md=(LL+RR)>>1;
            if(S[x][md+1].second<d)LL=md+1;
            else RR=md;
        }
        return Query(rt[S[x][LL].first],rt[S[x].back().first],k);
    }
    int ans=0;
    if(L<=mid)ans=std::max(ans,query(ls,l,mid,L,R,k,d));
    if(mid<R)ans=std::max(ans,query(rs,mid+1,r,L,R,k,d));
    return ans;
}
int main(){
#ifndef ONLINE_JUDGE
    freopen("4585.in","r",stdin);
    freopen("4585.out","w",stdout);
#endif
    int n=gi(),m=gi();
    for(int i=1;i<=n;++i)Insert(i-1,gi());
    int T=0,opt,l,r,x,d;
    for(int i=1;i<=4*n;++i)S[i].push_back(std::make_pair(0,0));
    for(int i=1;i<=m;++i){
        opt=gi();
        if(opt==0){
            x=gi(),d=gi(),++T;
            update(1,1,n,x,d,T);
        }else{
            l=gi(),r=gi(),x=gi(),d=gi();
            int ans=Query(rt[l-1],rt[r],x);
            if(d)ans=std::max(ans,query(1,1,n,l,r,x,T-d+1));
            printf("%d\n",ans);
        }
    }
    return 0;
}
posted @ 2018-07-31 17:12  菜狗xzz  阅读(274)  评论(0编辑  收藏  举报