【LibreOJ】#6396. 「THUPC2018」弗雷茲的玩具商店 / Toyshop 線段樹+完全背包
阿新 • • 發佈:2018-05-23
給定 註意 線段 fin names AI 循環 else https
【題目】#6396. 「THUPC2018」弗雷茲的玩具商店 / Toyshop
【題意】給定一個長度為n的物品序列,每個物品有價值、不超過m的重量。要求支持以下三種操作:1.物品價值區間加減,2.物品重量區間加(超過m部分取模),3.區間物品求解容量為m的完全背包數組。\(n \leq 2*10^5,m \leq 60,Q \leq 3*10^4\)。
【算法】線段樹+完全背包
顯然,每個重量只需要保留價值最大的物品。
然後就很簡單了,線段樹每個維護一個數組c[x]表示重量x的最大價值,區間循環和區間加減,每次詢問將區間m個重量的最大價值拿出來做完全背包。註意初始化為-inf(否則相當於有價值為0的物品,之後進行物品價值加減後就會幹擾答案了)。
復雜度\(O(nm\ \ log\ \ n+m^2)\)。
#include<cstdio> #include<cstring> #include<algorithm> #define ll long long #define lowbit(x) (x&-x) bool isdigit(char c){return c>=‘0‘&&c<=‘9‘;} int read(){ int s=0,t=1;char c; while(!isdigit(c=getchar()))if(c==‘-‘)t=-1; do{s=s*10+c-‘0‘;}while(isdigit(c=getchar())); return s*t; } using namespace std; const int maxn=200010,M=70; const ll inf=1ll<<60; int n,m,w[maxn],v[maxn]; ll C[M],f[M],D[M];//chong fu X struct tree{int l,r,w_delta,v_delta;ll c[M];}t[maxn*4]; ll max(ll a,ll b){return a<b?b:a;} void up(int k){ for(int i=1;i<=m;i++)t[k].c[i]=max(t[k<<1].c[i],t[k<<1|1].c[i]); } void w_modify(int k,int x){ t[k].w_delta+=x; for(int i=1;i<=m;i++)D[(i-1+x)%m+1]=t[k].c[i]; for(int i=1;i<=m;i++)t[k].c[i]=D[i]; } void v_modify(int k,int x){ t[k].v_delta+=x; for(int i=1;i<=m;i++)t[k].c[i]+=x; } void down(int k){ if(t[k].w_delta){ w_modify(k<<1,t[k].w_delta);w_modify(k<<1|1,t[k].w_delta); t[k].w_delta=0; } if(t[k].v_delta){ v_modify(k<<1,t[k].v_delta);v_modify(k<<1|1,t[k].v_delta); t[k].v_delta=0; } } void build(int k,int l,int r){ for(int i=1;i<=m;i++)t[k].c[i]=-inf;//-inf no influense t[k].l=l;t[k].r=r; if(l==r){t[k].c[w[l]]=v[l];return;}//return int mid=(l+r)>>1; build(k<<1,l,mid);build(k<<1|1,mid+1,r); up(k); } void w_fix(int k,int l,int r,int x){ if(l<=t[k].l&&t[k].r<=r){w_modify(k,x);return;} down(k);// int mid=(t[k].l+t[k].r)>>1; if(l<=mid)w_fix(k<<1,l,r,x); if(r>mid)w_fix(k<<1|1,l,r,x); up(k); } void v_fix(int k,int l,int r,int x){ if(l<=t[k].l&&t[k].r<=r){v_modify(k,x);return;} down(k);// int mid=(t[k].l+t[k].r)>>1; if(l<=mid)v_fix(k<<1,l,r,x); if(r>mid)v_fix(k<<1|1,l,r,x); up(k); } void query(int k,int l,int r){ if(l<=t[k].l&&t[k].r<=r){ for(int i=1;i<=m;i++)C[i]=max(C[i],t[k].c[i]); return;//return } down(k);//use down int mid=(t[k].l+t[k].r)>>1; if(l<=mid)query(k<<1,l,r); if(r>mid)query(k<<1|1,l,r); } int main(){ n=read();m=read(); for(int i=1;i<=n;i++)w[i]=read(); for(int i=1;i<=n;i++)v[i]=read(); build(1,1,n); int Q=read(); while(Q--){ int kind=read(),l=read(),r=read(); if(kind==1){ int x=read(); w_fix(1,l,r,x); } else if(kind==2){ int x=read(); v_fix(1,l,r,x); } else{ for(int i=1;i<=m;i++)C[i]=0,f[i]=0;//long long query(1,l,r); for(int i=1;i<=m;i++){ for(int j=i;j<=m;j++){ f[j]=max(f[j],f[j-i]+C[i]); } } ll ans=0;for(int i=1;i<=m;i++)ans+=f[i];printf("%lld ",ans);//long long ans=0;for(int i=1;i<=m;i++)ans^=f[i];printf("%lld\n",ans); } } return 0; }
【LibreOJ】#6396. 「THUPC2018」弗雷茲的玩具商店 / Toyshop 線段樹+完全背包