P9129 [USACO23FEB] Piling Papers G

先考虑 \(1\sim n\) 的时候怎么做,差分一下,只需要求 \(1\sim p\) 就行。先考虑朴素的时候,设 \(f_{i,j,k=0/1/2}\) 表示对于前 \(i\) 个纸片,已经补了 \(j\) 个位置了,当前的数分别小于,等于,大于 \(p\) 数字。

对于题目要求的前插后插很难用这个状态去实现,于是把 \(j\) 给改一下,表示为 \(f_{i,l,r,k=0/1/2}\) 已经补完了 \(l\sim r\) 位,其他的定义跟朴素一样,那这样就很好求出来了。

再考虑一下 \(ql\sim qr\),提前预处理出来 \(Ans_{ql,qr}\),把状态 \(i\) 改掉:

\[Ans_{ql,qr}=\sum\limits_{i=1}^m f_{i,m,0/1}+[i\neq1]f_{i,m,2} \]

时间复杂度为:\(O(n^2\lg^2 p+q)\)

::::info[\(\mathscr{Code:}\)]

#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstdio>
#include<cstring>

#define ll long long
// #define int ll
#define pii pair<int,int>
#define ull unsigned long long
using namespace std;
const int mod=1e9+7;
const int inf=0x3f3f3f3f;
char buf[1<<21], *p1=buf,*p2=buf;
#define gc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
#define getchar() gc()
ll rd(){
	ll s=0;char ch=getchar();bool fu=0;
	while(ch<'0'||ch>'9')ch=='-'?fu=1:0,ch=getchar();
	while(ch>='0'&&ch<='9')s=(s<<1)+(s<<3)+(ch^48),ch=getchar();
	return fu?-s:s;
}

const int N=310;
int n,a[N],cur[N],cnt;
ll ansA[N][N],A,B,ansB[N][N],f[N][N][3];

void getnum(ll a){
	while(a){
		cur[++cnt]=a%10;
		a/=10;
	}
	reverse(cur+1,cur+cnt+1);
}

static inline ll add(ll a,ll b){return a+b>=mod?a+b-mod:a+b;}
static inline void upd(ll &a,ll b){(a+=b)>=mod?a-=mod:0;}
static inline int calc(ll a,ll b){
	if(a<b)return 0;
	if(a==b)return 1;
	return 2;
}

void init(){
	getnum(A-1);
	for(int i=1;i<=n;++i){
		memset(f,0,sizeof(f));
		for(int j=i;j<=n;++j){
			for(int l=1;l<=cnt;++l)
				for(int r=cnt;r>l;--r){
					if(a[j]>cur[l]){
						upd(f[l][r][2],f[l+1][r][0]);
						upd(f[l][r][2],f[l+1][r][1]);
						upd(f[l][r][2],f[l+1][r][2]);
					}else if(a[j]==cur[l]){
						upd(f[l][r][0],f[l+1][r][0]);
						upd(f[l][r][1],f[l+1][r][1]);
						upd(f[l][r][2],f[l+1][r][2]);
					}else{
						upd(f[l][r][0],f[l+1][r][0]);
						upd(f[l][r][0],f[l+1][r][1]);
						upd(f[l][r][0],f[l+1][r][2]);
					}
					upd(f[l][r][0],f[l][r-1][0]);
					upd(f[l][r][calc(a[j],cur[r])],f[l][r-1][1]);
					upd(f[l][r][2],f[l][r-1][2]);
				}
			for(int k=1;k<=cnt;++k)upd(f[k][k][calc(a[j],cur[k])],2);
			for(int k=1;k<=cnt;++k){
				upd(ansA[i][j],f[k][cnt][0]);
				upd(ansA[i][j],f[k][cnt][1]);
				if(k!=1)upd(ansA[i][j],f[k][cnt][2]);
			}
		}
	}
	cnt=0;
	getnum(B);
	for(int i=1;i<=n;++i){
		memset(f,0,sizeof(f));
		for(int j=i;j<=n;++j){
			for(int l=1;l<=cnt;++l)
				for(int r=cnt;r>l;--r){
					if(a[j]>cur[l]){
						upd(f[l][r][2],f[l+1][r][0]);
						upd(f[l][r][2],f[l+1][r][1]);
						upd(f[l][r][2],f[l+1][r][2]);
					}else if(a[j]==cur[l]){
						upd(f[l][r][0],f[l+1][r][0]);
						upd(f[l][r][1],f[l+1][r][1]);
						upd(f[l][r][2],f[l+1][r][2]);
					}else{
						upd(f[l][r][0],f[l+1][r][0]);
						upd(f[l][r][0],f[l+1][r][1]);
						upd(f[l][r][0],f[l+1][r][2]);
					}
					upd(f[l][r][0],f[l][r-1][0]);
					upd(f[l][r][calc(a[j],cur[r])],f[l][r-1][1]);
					upd(f[l][r][2],f[l][r-1][2]);
				}
			for(int k=1;k<=cnt;++k)upd(f[k][k][calc(a[j],cur[k])],2);
			for(int k=1;k<=cnt;++k){
				upd(ansB[i][j],f[k][cnt][0]);
				upd(ansB[i][j],f[k][cnt][1]);
				if(k!=1)upd(ansB[i][j],f[k][cnt][2]);
			}
		}
	}
}

inline void Solve(){
	n=rd(),A=rd(),B=rd();
	for(int i=1;i<=n;++i)a[i]=rd();
	init();
	int q=rd();
	while(q--){
		int ql=rd(),qr=rd();
//		cout<<"==> "<<ansA[ql][qr]<<" "<<ansB[ql][qr]<<"\n";
		printf("%lld\n",(ansB[ql][qr]+mod-ansA[ql][qr])%mod);
	}
}

signed main(){
	// freopen("input.in","r",stdin);
	// ios::sync_with_stdio(false);
	// cin.tie(0), cout.tie(0);
	int T=1;
	while(T--)Solve();
	return 0;
}

::::

posted @ 2026-05-27 16:03  static_inline  阅读(14)  评论(0)    收藏  举报