【题解】Luogu P7432 [THUPC 2017] 钦妹的玩具商店

分块,设块长为 \(B\),预处理 \(f_{l,r,x}\) 表示仅考虑 \([1,l]\cup[r,\frac{n}{B}]\) 中的玩具,花 \(x\) 元的最大愉悦度。询问时向 \(f_{bel_l-1,bel_r+1}\) 中加入 \(l\)\(r\) 所在块内的玩具即可。\(bel_l\) 表示 \(l\) 所在块。

使用二进制优化多重背包,分析时间复杂度:

  • 预处理 \(O(\frac{n^2m\log{n}}{B})\)
  • 询问 \(O(qmB\log{n})\)

\(B=\sqrt{n}\),时间复杂度为 \(O((n+q)m\sqrt{n}\log{n})\),空间复杂度 \(O(nm)\)

#include<bits/stdc++.h>
#define int long long
#define il inline

using namespace std;
namespace asbt{
namespace cplx{bool begin;}
const int maxn=1e3+5,maxm=40,mod=1e8+7;
int T,n,m,q,blen,bnum;
int a[maxn],b[maxn],c[maxn];
int bel[maxn],st[maxm],ed[maxm];
struct DP{
	int f[maxn];
	il void init(){
		for(int i=0;i<=m;i++){
			f[i]=0;
		}
	}
	il int operator[](int x){
		return f[x];
	}
	il void upd(int x){
		int a=asbt::a[x],b=asbt::b[x],c=asbt::c[x];
		for(int i=1;i<=c;i<<=1){
			for(int j=m;j>=i*a;j--){
				f[j]=max(f[j],f[j-i*a]+i*b);
			}
			c-=i;
		}
		for(int i=m;i>=c*a;i--){
			f[i]=max(f[i],f[i-c*a]+c*b);
		}
	}
}dp[maxm][maxm];
il void solve(){
	cin>>n>>m>>q;
	for(int i=1;i<=n;i++){
		cin>>a[i];
	}
	for(int i=1;i<=n;i++){
		cin>>b[i];
	}
	for(int i=1;i<=n;i++){
		cin>>c[i];
	}
	blen=sqrt(n);
	bnum=(n+blen-1)/blen;
	for(int i=1;i<=bnum;i++){
		st[i]=ed[i-1]+1;
		ed[i]=min(ed[i-1]+blen,n);
		for(int j=st[i];j<=ed[i];j++){
			bel[j]=i;
		}
	}
	for(int i=0;i<=bnum;i++){
		if(!i){
			dp[i][bnum+1].init();
		}
		else{
			dp[i][bnum+1]=dp[i-1][bnum+1];
			for(int j=st[i];j<=ed[i];j++){
				dp[i][bnum+1].upd(j);
			}
		}
		for(int j=bnum;j>i;j--){
			dp[i][j]=dp[i][j+1];
			for(int k=st[j];k<=ed[j];k++){
				dp[i][j].upd(k);
			}
		}
	}
	int ans1=0,ans2=0;
	while(q--){
		int l,r;
		cin>>l>>r;
		l=(l+ans1-1)%n+1;
		r=(r+ans1-1)%n+1;
		if(l>r){
			swap(l,r);
		}
		DP ans=dp[bel[l]-1][bel[r]+1];
		for(int i=st[bel[l]];i<l;i++){
			ans.upd(i);
		}
		for(int i=ed[bel[r]];i>r;i--){
			ans.upd(i);
		}
		ans1=ans2=0;
		for(int i=1;i<=m;i++){
			ans1+=ans[i];
			ans2^=ans[i];
		}
		ans1%=mod;
		cout<<ans1<<" "<<ans2<<"\n";
	}
}
namespace cplx{
	bool end;
	il double usdmem(){return (&begin-&end)/1048576.0;}
}
signed main(){
//	cout<<cplx::usdmem();
	ios::sync_with_stdio(0),cin.tie(0);
	cin>>T;
	while(T--){
		solve();
	}
	return 0;
}
}
signed main(){return asbt::main();}
posted @ 2025-02-08 10:45  zhangxy__hp  阅读(12)  评论(0)    收藏  举报