题解:P12493 [集训队互测 2024] 子集和
nullqtr_pwp · · 题解
考虑把背包看成一个黑盒:支持
如果只需要处理所有
考虑
拓展这个猫树分治做法,将所有询问套路化的差分为
事实上并不需要拆成
综上,我们可以使用
int ans[QR],n,m,zsy,a[maxn],b[maxn];
#define poly vector<int>
poly mrg(poly x,poly y){
poly res(m);
F(i,0,m-1)res[i]=add(x[i],y[i]);
return res;
}
poly ins(poly x,int pos){
poly res=x;
F(i,0,m-1)inc(res[i+a[pos]>=m?i+a[pos]-m:i+a[pos]],x[i]);
F(i,0,m-1)inc(res[i+b[pos]>=m?i+b[pos]-m:i+b[pos]],x[i]);
return res;
}
void init(poly &x){
x.resize(m);
F(i,0,m-1)x[i]=(i==0);
}
void init1(poly &x){
x.resize(m);
for(int &i:x)i=0;
}
int qry(poly &x,poly &y){
int ans=0;
F(i,0,m-1)inc(ans,1ll*x[i]*y[i==0?0:m-i]%mod);
return ans;
}
vector<array<int,4>>qu[maxn<<2];
void ins_query(int o,int l,int r,int ql,int qr,int coef,int id){
if(ql>qr||ql<1||qr>n)return;
const int mid=(l+r)>>1;
if(ql<=mid&&mid<qr)return qu[o].push_back({ql,qr,coef,id}),void();
if(qr<=mid)ins_query(o<<1,l,mid,ql,qr,coef,id);
if(ql>mid)ins_query(o<<1|1,mid+1,r,ql,qr,coef,id);
}
poly pre[maxn],suf[maxn],psum[maxn],ssum[maxn],f[maxn],dp[maxn];
void dfs(int o,int l,int r){
if(l==r)return;
const int mid=(l+r)>>1;
dfs(o<<1,l,mid),dfs(o<<1|1,mid+1,r);
if(qu[o].empty())return;
poly F;
auto sol=[&](auto &self,int L,int R){
if(L==R)return f[L]=F,void();
int mid=(L+R)>>1;
poly tmp=F;
F(i,L,mid)F=ins(F,i);
self(self,mid+1,R);
F=tmp;
F(i,mid+1,R)F=ins(F,i);
self(self,L,mid);
};
F=psum[l-1],sol(sol,l,mid);
F=ssum[r+1],sol(sol,mid+1,r);
poly lef=pre[l-1],rig=suf[r+1];
F(i,l,mid)lef=ins(lef,i);
F(i,mid+1,r)rig=ins(rig,i);
dp[l-1]=lef,dp[r+1]=rig;
F(i,l,mid)dp[i]=mrg(dp[i-1],f[i]);
dF(i,r,mid+1)dp[i]=mrg(dp[i+1],f[i]);
for(auto&[ql,qr,coef,id]:qu[o]){
int val=qry(dp[ql],dp[qr]);
if(coef<0)dec(ans[id],val);
else inc(ans[id],val);
}
}
void solve(){
cin>>n>>m>>zsy;
F(i,1,n)cin>>a[i]>>b[i];
init(psum[0]),init(ssum[n+1]);
F(i,1,n)psum[i]=ins(psum[i-1],i);
dF(i,n,1)ssum[i]=ins(ssum[i+1],i);
init1(pre[0]),init1(suf[n+1]);
F(i,1,n)pre[i]=mrg(ins(pre[i-1],i),psum[i-1]);
dF(i,n,1)suf[i]=mrg(ins(suf[i+1],i),ssum[i+1]);
F(i,1,zsy){
int l1,r1,l2,r2;cin>>l1>>r1>>l2>>r2;
ins_query(1,1,n,r1,l2,1,i);
ins_query(1,1,n,r1,r2+1,-1,i);
ins_query(1,1,n,l1-1,l2,-1,i);
ins_query(1,1,n,l1-1,r2+1,1,i);
}
dfs(1,1,n);
F(i,1,zsy)cout<<ans[i]<<'\n';
}