思路:
暴力:
对于f[i]考虑暴力枚举每一个长为i的区间,判断是否可以
优化:
只需要预处理出每一个左端点对应的最小满足所有限制的右端点,然后对所有预处理出来的区 间按大小排序用q[i]记录,那么求f[k],只需要找到有多少个有效的q[i]<=k即可(有效q[i]指的是q[i]所代表的区间的左端点 l<=n-k+1)
预处理可以尺取,找到有效的q[i]可以线性推,具体看代码
#define ll long long
using namespace std;
const ll mod=1e9+7;
const int N=2e6+10;
ll b[N],c[N],a[N],w[N]={0},q[N],bj[N]={0};
int main()
{
ll t,i,n,g,j,m,k,h,l,r,mid,max1,min1,p,i1,j1,v,x0,y0,x1,y1,x,y,r1,r2;
scanf("%lld%lld",&n,&m);
for(i=1;i<=m;i++)scanf("%lld",&a[i]);
for(i=1;i<=m;i++)scanf("%lld",&b[i]);
for(i=1;i<=m;i++)scanf("%lld",&c[i]);
min1=1e18;g=-1;
//预处理所有限制中每种数的第一个大于它的数的最大值,用bj[i]记录
//预处理所有限制中的最小的最大值,用min1记录
//预处理所有限制中的最大的最小值,用g记录
for(i=1;i<=m;i++)
q[1]=a[i];q[2]=b[i];q[3]=c[i];
sort(q+1,q+1+3);
g=max(g,q[1]);min1=min(min1,q[3]);
if(q[2]<q[3])bj[q[2]]=max(bj[q[2]],q[3]);
if(q[1]<q[2])bj[q[1]]=max(bj[q[1]],q[2]);
else
if(q[1]<q[3])
bj[q[1]]=max(bj[q[1]],q[3]);
}
//w数组记录每个左端点对应的最小满足限制的右端点,q数组记录w数组对应串区间长度
w[1]=g;q[1]=g;
for(i=2;i<=n;i++){
if(min1<i)break;//某个限制的最大值都要小于i,则一定不能以它为左端点
w[i]=max(w[i-1],bj[i-1]);//思考去掉了i-1这个座位后的影响,推得w[i]
q[i]=w[i]-i+1;
}
p=i-1;
sort(q+1,q+1+p);
h=0;m=1;
//无效区间个数用h表示
for(i=1,j=1;i<=n;i++){
m=m*i%mod;
while(q[j]<=i&&j<=p)j++;
printf("%lld ",(j-1-h)*m%mod);
if(w[n-i+1]!=0)h++;
}
}