P3724 [AHOI2017/HNOI2017] 大佬 题解

题目链接:P3724 [AHOI2017/HNOI2017] 大佬

水黑。看到数据范围考虑暴力,跑一下发现 100 天也只够构造出 8.5e6 个不同的数。由于每天的操作除了增加信心值都是等价的,所以可以直接在开头跑一个 dp 求出最多的空闲天数。0 次嘲讽和 1 次嘲讽很好处理,两次嘲讽考虑用一个双指针,注意维护的应该是最大的 嘲讽值-需要使用的天数,因为本来这些天数可以还嘴。爆搜的部分应该使用哈希表判重,因为数据比较水就用了set判重,实测本地机子在满的 100 天的时候跑了 22s,洛谷最大点跑 1s。

代码:

#include<bits/stdc++.h>
#define time(null) chrono::steady_clock::now().time_since_epoch().count()
#define int long long
#define uint unsigned long long
#define debug() cout<<"come here\n"
#define INF 0x3f3f3f3f3f3f3f3f
#define pii pair<int,int>
#define pb push_back
#define Code return
#define by 0
#define MCYYDS ;
using namespace std;
int qpow(int a,int b,int p=INF){int ret=1;while(b){if(b&1)ret=(ret*a)%p;a=(a*a)%p;b>>=1;}return ret;}
inline int read(){int ret=0,f=1;char ch=getchar();while(ch<'0'||ch>'9')f=(ch=='-'?-1:f),ch=getchar();while(ch>='0'&&ch<='9')ret=(ret<<3)+(ret<<1)+(ch^48),ch=getchar();return ret*f;}
inline void write(int x){if(x<0){putchar('-');write(-x);return ;}if(x>9)write(x/10);putchar((char)(x%10+48));}
inline void writech(int x,char ch){write(x);putchar(ch);}
int a[105],w[105],dp[105][105],n,m,mc,mx;
struct node{
	int step,f,l;
};
queue<node> q;
set<pii> s;
vector<pii> vc;
void init() 
{
	q.push({1,1,0});
	s.insert({1,1});
	vc.pb({1,1});
	int cnt=0;
	while(q.size())
	{
		node u=q.front();
		q.pop();
		if(u.step<mx&&u.f*(u.l+1)<=100000000)
		{
			s.insert({u.f,u.step+1});
			q.push({u.step+1,u.f,u.l+1});
		}
		if(u.step<mx&&u.l>1&&u.f*u.l<=100000000&&s.find({u.f*u.l,u.step+1})==s.end())
		{
			s.insert({u.f*u.l,u.step+1});
			vc.pb({u.f*u.l,u.step+1});
			q.push({u.step+1,u.f*u.l,u.l});
		}
//		cnt++;
//		if(cnt%1000000==0)writech(cnt,'\n');
	}
	sort(vc.begin(),vc.end());
	vector<pii> vc1;
	for(auto x:vc)
	{
		if(vc1.size()==0||vc1.back().first!=x.first)vc1.pb(x);
	}
	swap(vc,vc1);
}
signed main()
{
//	ios::sync_with_stdio(0);
//	cin.tie(0);
//	cout.tie(0);
	n=read(),m=read(),mc=read();
	for(int i=1;i<=n;i++)
	{
		a[i]=read();
	}
	for(int i=1;i<=n;i++)
	{
		w[i]=read();
	}
	memset(dp,0x3f,sizeof(dp));
	dp[0][mc]=0;
	mx=0;
	for(int i=1;i<=n;i++)
	{
		for(int j=a[i];j<=mc;j++)
		{
			dp[i][j-a[i]]=min(dp[i][j-a[i]],dp[i-1][j]);
			dp[i][min(mc,j-a[i]+w[i])]=min(dp[i][min(mc,j-a[i]+w[i])],dp[i-1][j]+1);
			mx=max(mx,i-dp[i][j-a[i]]);
			mx=max(mx,i-dp[i][min(mc,j-a[i]+w[i])]);
		}
	}
//	cout<<mx<<'\n';
	init();
//	cout<<vc.size()<<'\n';
	for(int i=1;i<=m;i++)
	{
		int val=read();
		if(val<=mx)
		{
			puts("1");
			continue;
		}
		bool flag=0;
		int mxx=-INF,j=0;
		for(int i=vc.size()-1;i>=0;i--)
		{
			if(vc[i].first<=val&&vc[i].first-vc[i].second+mx>=val)
			{
				puts("1");
				flag=1;
				break;
			}
			while(j<vc.size()&&vc[i].first+vc[j].first<=val)
			{
				mxx=max(mxx,vc[j].first-vc[j].second);
				j++;
			}
			if(mx+vc[i].first+mxx-vc[i].second>=val)
			{
				flag=1;
				puts("1");
				break;
			}
		}
		if(!flag)puts("0");
	}
	Code by MCYYDS
}

posted @ 2026-07-13 18:59  MCYYDS  阅读(24)  评论(0)    收藏  举报