列表

详情


NC20120. [HNOI2017]大佬

描述

人们总是难免会碰到大佬。他们趾高气昂地谈论凡人不能理解的算法和数据结构,走到任何一个地方,大佬的气场就能让周围的人吓得瑟瑟发抖,不敢言语。 你作为一个 OIER,面对这样的事情非常不开心,于是发表了对大佬不敬的言论。 大佬便对你开始了报复,你也不示弱,扬言要打倒大佬。

现在给你讲解一下什么是大佬,大佬除了是神犇以外,还有着强大的自信心,自信程度可以被量化为一个正整数 , 想要打倒一个大佬的唯一方法是摧毁 Ta 的自信心,也就是让大佬的自信值等于 0(恰好等于 0,不能小于 0)。 由于你被大佬盯上了,所以你需要准备好 天来和大佬较量,因为这 n 天大佬只会嘲讽你动摇你的自信,到了第 天,如果大佬发现你还不服,就会直接虐到你服,这样你就丧失斗争的能力了。

你的自信程度同样也可以被量化,我们用 来表示你的自信值上限

在第 i天(),大佬会对你发动一次嘲讽,使你的自信值减小 ,如果这个时刻你的自信值小于 0 了,那么你就丧失斗争能力,也就失败了(特别注意你的自信值为 0 的时候还可以继续和大佬斗争)。 在这一天, 大佬对你发动嘲讽之后,如果你的自信值仍大于等于 0,你能且仅能选择如下的行为之一:

  1. 还一句嘴,大佬会有点惊讶,导致大佬的自信值 C 减小 1

  2. 做一天的水题,使得自己的当前自信值增加 , 并将新自信值和自信值上限 mc 比较,若新自信值大于 mc,则新自信值更新为 mc。例如, , 当前自信值为 40, 若,则新自信值为 45,若 ,则新自信值为 50

  3. 让自己的等级值 L1

  4. 让自己的讽刺能力 F 乘以自己当前等级 L,使讽刺能力 F 更新为

  5. 怼大佬,让大佬的自信值 C 减小 F。并在怼完大佬之后,你自己的等级 L 自动降为 0,讽刺能力 F 降为 1。由于怼大佬比较掉人品,所以这个操作只能做不超过 2 次。

特别注意的是,在任何时候,你不能让大佬的自信值为负,因为自信值为负,对大佬来说意味着屈辱,而大佬但凡遇到屈辱就会进化为更厉害的大佬直接虐飞你。在第 1 天,在你被攻击之前,你的自信是满的(初始自信值等于自信值上限 mc), 你的讽刺能力 F1, 等级是 0

现在由于你得罪了大佬,你需要准备和大佬正面杠,你知道世界上一共有 个大佬,他们的嘲讽时间都是 n 天,而且第 i 天的嘲讽值都是 。不管和哪个大佬较量,你在第 i 天做水题的自信回涨都是 。 这 m 个大佬中只会有一个来和你较量( n 天里都是这个大佬和你较量),但是作为你,你需要知道对于任意一个大佬,你是否能摧毁他的自信,也就是让他的自信值恰好等于 0。和某一个大佬较量时,其他大佬不会插手。

输入描述

第一行三个正整数 n,m,mc 。分别表示有 n 天和 m 个大佬,你的自信上限为 mc
接下来一行是用空格隔开的 n 个数,其中第 个表示
接下来一行是用空格隔开的 n 个数,其中第 个表示
接下来 m 行,每行一个正整数,其中第 行的正整数 表示第 k 个大佬的初始自信值。

输出描述

m 行,如果能战胜第 k 个大佬(让他的自信值恰好等于 0 ),那么第k行输出 1 ,否则输出0

示例1

输入:

10 20 100
22 18 15 16 20 19 33 15 38 49
92 14 94 92 66 94 1 16 90 51
4
5
9
338
5222
549
7491
9
12
3288
3
1
2191
833
3
6991
2754
3231
360
6

输出:

1
1
1
0
0
0
0
1
1
0
1
1
0
0
1
0
0
0
0
1

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++14(g++5.4) 解法, 执行用时: 318ms, 内存消耗: 28772K, 提交时间: 2019-10-29 22:08:10

// luogu-judger-enable-o2
//It is made by M_sea
#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <queue>
#define re register
using namespace std;

template<typename T>
inline void chkmax(T& x,T y) { if (y>x) x=y; }
template<typename T>
inline void chkmin(T& x,T y) { if (y<x) x=y; }
inline int read() {
    int X=0,w=1; char c=getchar();
    while (c<'0'||c>'9') { if (c=='-') w=-1; c=getchar(); }
    while (c>='0'&&c<='9') X=X*10+c-'0',c=getchar();
    return X*w;
}

const int N=100+10;
const int MOD=1000007;
const int inf=0x3f3f3f3f;

struct hash_table {
    struct oho { int u,v,nxt; } e[2000000];
    int head[MOD+5],cnt;
    inline void insert(int u,int v) {
        int tmp=(1ll*u*100+v)%MOD;
        e[++cnt]=(oho){u,v,head[tmp]},head[tmp]=cnt;
    }
    inline int query(int u,int v) {
        int tmp=(1ll*u*100+v)%MOD;
        for (re int i=head[tmp];i;i=e[i].nxt)
            if (e[i].u==u&&e[i].v==v) return 1;
        return 0;
    }
} H;

int n,m,mc,d,maxc;
int a[N],w[N],c[N];
int f[N][N];

struct node { int s,F,L; };
struct state { int s,F; } S[2000000];
bool operator <(state a,state b) {
    if (a.F==b.F) return a.s<b.s;
    else return a.F<b.F;
}

int top=0;

inline void bfs() {
    queue<node> Q; Q.push((node){1,1,0});
    while (!Q.empty()) {
        node x=Q.front(); Q.pop();
        int s=x.s,F=x.F,L=x.L;
        if (s<d) {
            Q.push((node){s+1,F,L+1}); //level up
            if (L>1&&1ll*F*L<=1ll*maxc&&!H.query(F*L,s+1)) {
                Q.push((node){s+1,F*L,L}); //atk up
                S[++top]=(state){s+1,F*L};
                H.insert(F*L,s+1);
            }
        }
    }
}

int main() {
    n=read(),m=read(),mc=read();
    for (re int i=1;i<=n;++i) a[i]=read();
    for (re int i=1;i<=n;++i) w[i]=read();
    for (re int i=1;i<=m;++i) c[i]=read(),chkmax(maxc,c[i]);
    //dp
    for (re int i=1;i<=n;++i)
        for (re int j=a[i];j<=mc;++j) {
            chkmax(f[i][j-a[i]],f[i-1][j]+1);
            chkmax(f[i][min(mc,j-a[i]+w[i])],f[i-1][j]);
        }
    for (re int i=1;i<=n;++i)
        for (re int j=0;j<=mc;++j)
            chkmax(d,f[i][j]);
    //bfs
    bfs();
    //solve
    sort(S+1,S+top+1);
    for (re int i=1;i<=m;++i) {
        if (c[i]<=d) { puts("1"); continue; }
        int ans=0,mn=inf;
        for (re int j=top,k=1;j>=1;--j) {
            while (k<top&&S[j].F+S[k].F<=c[i]) chkmin(mn,S[k].s-S[k].F),++k;
            if (mn+S[j].s-S[j].F+c[i]<=d) { ans=1; break; }
            if (S[j].F<=c[i]&&c[i]-S[j].F+S[j].s<=d) { ans=1; break; }
        }
        printf("%d\n",ans);
    }
    return 0;
}

C++11(clang++ 3.9) 解法, 执行用时: 516ms, 内存消耗: 31496K, 提交时间: 2020-04-03 11:59:25

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<queue>
using namespace std;
#define ll long long
#define RG register
#define MAX 111
#define ft(i) zt[i].first
#define sd(i) zt[i].second
inline int read()
{
	RG int x=0,t=1;
	RG char ch=getchar();
	while((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
	if(ch=='-') t=-1,ch=getchar();
	while(ch<='9'&&ch>='0') x=x*10+ch-48,ch=getchar();
	return x*t;
}
int f[MAX][MAX];
int n,m,MC,Day,a[MAX],w[MAX],C[MAX];
struct Node
{
	int i,F,L;
};
pair<int,int> zt[1111111];
int tot,mx;
int MOD=1000007;
struct Hash
{
	struct Line
	{
		int x,y,next;
	}e[1111111];
	int h[1000007+1],cnt;
	void Add(int x,int y)
	{
		int pos=(1ll*x*101+y)%MOD;
		e[++cnt]=(Line){x,y,h[pos]};
		h[pos]=cnt;
	}
	bool Query(int x,int y)
	{
		int pos=(1ll*x*101+y)%MOD;
		for(int i=h[pos];i;i=e[i].next)
		if(e[i].x==x&&e[i].y==y) return true;
		return false;
	}
}Map;
void BFS()
{
	queue<Node> Q;
	Q.push((Node){1,1,0});
    while(!Q.empty())
    {
    	Node u=Q.front();
    	Q.pop();
    	if(u.i==Day) continue;
    	Q.push((Node){u.i+1,u.F,u.L+1});
    	if(u.L>1&&1ll*u.F*u.L<=1ll*mx&&!Map.Query(u.F*u.L,u.i+1))
    	{
    		Q.push((Node){u.i+1,u.F*u.L,u.L});
    		zt[++tot]=make_pair(u.F*u.L,u.i+1);
    		Map.Add(u.F*u.L,u.i+1);
		}
	}
}
int main()
{
	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();
	for(int i=1;i<=m;++i)
	mx=max(mx,C[i]=read());
	for(int i=1;i<=n;++i)
	for(int j=a[i];j<=MC;++j)
	{
		f[i][j-a[i]]=max(f[i-1][j]+1,f[i][j-a[i]]);
		f[i][min(j-a[i]+w[i],MC)]=max(f[i-1][j],f[i][min(j-a[i]+w[i],MC)]);
	}
	for(int i=1;i<=n;++i)
	for(int j=1;j<=MC;++j)
	Day=max(Day,f[i][j]);
	BFS();
	sort(&zt[1],&zt[tot+1]);
	for(int i=1;i<=m;++i)
	{
		if(C[i]<=Day) 
		{
			puts("1");
			continue;
		}
		bool fl=false;
		int mm=1e9;
		for(int j=tot,k=1;j;--j)
		{
			while(k<tot&&ft(k)+ft(j)<=C[i])
			mm=min(mm,sd(k)-ft(k)),++k;
			if(mm+C[i]-ft(j)<=Day-sd(j))
			{
				fl=true;
				break;
			}
			if(ft(j)<=C[i]&&C[i]-ft(j)<=Day-sd(j))
			{
				fl=true;
				break;
			}
		}
		fl? puts("1"):puts("0");
	}
	return 0;
}

上一题