$solution:$
好久没写数据结构了,那就写道简单题吧!
可以发现 $mleq 50$,所以可以去取在 $[l,r]$ 中当价格相同时愉悦值最高的做完全背包 $dp$ 。
发现修改价格与愉悦值修改操作可以在线段树上维护,只要暴力修改在乱搞一下即可。
时间复杂度 $O(nmlog n+q imes 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 ",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 ",sum,Xor); } } }