[THUPC2018] 弗雷兹的玩具商店

link

$solution:$

好久没写数据结构了,那就写道简单题吧!

可以发现 $m\leq 50$,所以可以去取在 $[l,r]$ 中当价格相同时愉悦值最高的做完全背包 $dp$ 。

发现修改价格与愉悦值修改操作可以在线段树上维护,只要暴力修改在乱搞一下即可。

时间复杂度 $O(nm\log n+q\times m^2)$ 。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define int long long
using namespace std;
inline int read(){
    int f=1,ans=0;char c=getchar();
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){ans=ans*10+c-'0';c=getchar();}
    return f*ans;
}
const int MAXN=200001;
struct Node{
    int val[61];
    void clear(){memset(val,-127/3,sizeof(val));}
}tmp[MAXN<<2];
int n,m;
Node operator+(Node x1,Node x2){
    Node x3;
    for(int i=1;i<=m;i++) x3.val[i]=max(x1.val[i],x2.val[i]);
    return x3;
}
int w[MAXN],c[MAXN];
int tagw[MAXN<<2],tagc[MAXN<<2];
struct Segment{
    void debug(Node t1){
        for(int i=1;i<=m;i++) printf("val(%d):%d\n",i,t1.val[i]);
        return;
    }
    void build(int k,int l,int r){
        if(l==r){
            tmp[k].clear();
            tmp[k].val[w[l]]=c[l];
            return;
        }
        int mid=l+r>>1;
        build(k<<1,l,mid),build(k<<1|1,mid+1,r);
        tmp[k]=tmp[k<<1]+tmp[k<<1|1];
        return;
    }
    Node Mw(int ps,int d){
        if(!d) return tmp[ps];
        Node t1;t1.clear();
        for(int i=1;i<=m;i++){
            if((i+d)%m==0) t1.val[m]=tmp[ps].val[i];
            else t1.val[(i+d)%m]=tmp[ps].val[i];
        }
        return t1;
    }
    Node Mc(int ps,int d){
        Node t1=tmp[ps];
        for(int i=1;i<=m;i++) t1.val[i]+=d;return t1;
    }
    void pushdownw(int k){
        tmp[k<<1]=Mw(k<<1,tagw[k]),tmp[k<<1|1]=Mw(k<<1|1,tagw[k]);
        tagw[k<<1]+=tagw[k],tagw[k<<1|1]+=tagw[k];
        tagw[k]=0;return;
    }
    void pushdownc(int k){
        tmp[k<<1]=Mc(k<<1,tagc[k]),tmp[k<<1|1]=Mc(k<<1|1,tagc[k]);
        tagc[k<<1]+=tagc[k],tagc[k<<1|1]+=tagc[k];
        tagc[k]=0;return;
    }
    void modify_w(int k,int l,int r,int x,int y,int d){
        if(x<=l&&r<=y){
            tmp[k]=Mw(k,d);
            tagw[k]+=d;return;
        }
        pushdownw(k);
        pushdownc(k);
        int mid=l+r>>1;
        if(x<=mid) modify_w(k<<1,l,mid,x,y,d);
        if(mid<y) modify_w(k<<1|1,mid+1,r,x,y,d);
        tmp[k]=tmp[k<<1]+tmp[k<<1|1];return;
    }
    void modify_c(int k,int l,int r,int x,int y,int d){
        if(x<=l&&r<=y){
            tmp[k]=Mc(k,d);
            tagc[k]+=d;return;
        }
        pushdownw(k);
        pushdownc(k);
        int mid=l+r>>1;
        if(x<=mid) modify_c(k<<1,l,mid,x,y,d);
        if(mid<y) modify_c(k<<1|1,mid+1,r,x,y,d);
        tmp[k]=tmp[k<<1]+tmp[k<<1|1];
        return;
    }
    Node Query(int k,int l,int r,int x,int y){
        if(x<=l&&r<=y) return tmp[k];
        pushdownw(k),pushdownc(k);
        int mid=l+r>>1;Node res;res.clear();
        if(x<=mid) res=res+Query(k<<1,l,mid,x,y);
        if(mid<y) res=res+Query(k<<1|1,mid+1,r,x,y);
        tmp[k]=tmp[k<<1]+tmp[k<<1|1];
        return res;
    }
}segment;
int q,f[61];
signed main(){
//    freopen("1.in","r",stdin);
    n=read(),m=read();
    for(int i=1;i<=n;i++) w[i]=read();
    for(int i=1;i<=n;i++) c[i]=read();
    q=read();
    segment.build(1,1,n);
    while(q--){
        int opt=read(),l=read(),r=read();
        if(opt==1){
            int d=read();
            segment.modify_w(1,1,n,l,r,d);
        }
        if(opt==2){
            int d=read();
            segment.modify_c(1,1,n,l,r,d);
        }
        if(opt==3){
            memset(f,-127/3,sizeof(f));
            f[0]=0;
            Node g=segment.Query(1,1,n,l,r);
            for(int i=1;i<=m;i++)
                for(int j=i;j<=m;j++) f[j]=max(f[j],f[j-i]+g.val[i]);
            int sum=0,Xor=0;
            for(int i=1;i<=m;i++) f[i]=max(f[i],f[i-1]);
            for(int i=1;i<=m;i++) sum+=f[i],Xor^=f[i];
            printf("%lld %lld\n",sum,Xor);
        }
    }
}
View Code

猜你喜欢

转载自www.cnblogs.com/si-rui-yang/p/11204053.html