luogu P6567 [NOI Online #3 入门组]买表
题面传送门
来一发不用单调队列的解法。
循环还是单调队列的循环,只不过把单调队列换成一个变量记录有几个\(1\),循环时加减一下就好了。时间复杂度\(O(nm)\)
代码实现:
#include<cstdio>
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
using namespace std;
int n,m,k,a[1039],b[1039],t[200039],q[1000039],dp[4][1000039],now,last,ans,tot;
inline void read(int &x){
char s=getchar();x=0;
while(s<'0'||s>'9') s=getchar();
while(s>='0'&&s<='9') x=(x<<3)+(x<<1)+(s^48),s=getchar();
}
int main(){
//freopen("watch.in","r",stdin);
//freopen("watch.out","w",stdout);
register int i,j,k,head,tail,now,last;
read(n);read(m);
for(i=1;i<=n;i++) read(a[i]),read(b[i]);
for(i=1;i<=m;i++) read(t[i]),ans=max(ans,t[i]);
dp[1][0]=dp[0][0]=1;
for(i=1;i<=n;i++){
now=i&1;last=now^1;
for(j=0;j<a[i];j++){
tot=0;
for(k=j;k<=ans;k+=a[i]){
if(k>=a[i]*b[i]+a[i]) tot-=dp[last][k-a[i]*b[i]-a[i]];
tot+=dp[last][k];
dp[now][k]=tot?1:0;
}
}
// for(j=0;j<=ans;j++) printf("%d ",dp[now][j]);
// printf("\n");
}
for(i=1;i<=m;i++){
// printf("%d\n",dp[n&1][t[i]]);
if(dp[n&1][t[i]])putchar('Y'),putchar('e'),putchar('s'),putchar('\n');
else putchar('N'),putchar('o'),putchar('\n');
}
}