#10178. 「一本通 5.5 例 4」旅行问题

题目

loj链接

思路

瞎jb写,考试最后5min找到bug,考玩10minAC,成功GG

这题没啥算法(感觉跟dp有点关系?)

他们说正解是单调队列,鬼知道咋用,反正我是O(n)

题目数据最大好像是1e5,大家也可以写个O(nlogn)的水一水拉

就是预处理个 f1 ,f2,代码里的注释很详细了

#include <iostream>
#include <cstring>
#include <cstdio>
#define ll long long
using namespace std;
const int maxn=1e6+7;
const ll inf=0x3f3f3f3f3f3f3f3fLL;
int n,a[maxn],nxt[maxn];
ll f1[maxn],f2[maxn],sum_jia[maxn],sum_jian[maxn];
bool is_ok[maxn];
ll min(ll a,ll b) {
	return a < b ? a: b;
}
int read() {
	int x=0,f=1;
	char s=getchar();
	for(; s>'9'||s<'0'; s=getchar()) if(s=='-') f=-1;
	for(; s>='0'&&s<='9'; s=getchar()) x=x*10+s-'0';
	return x*f;
}
int main() {
	n=read();
	for(int i=1; i<=n; ++i) {
		a[i]=read(),nxt[i]=read();
		sum_jia[i]=sum_jia[i-1]+a[i];
		sum_jian[i]=sum_jian[i-1]+nxt[i];
	}
	//f1 表示 从 1 出发 到达 i 的最少初始值
	ll sheng=0,ma=-inf;
	for(int i=2; i<=n; ++i) {
		sheng+=a[i-1]-nxt[i-1];
		ma=max(ma,-sheng);
		f1[i]=ma;
	}
	
	//f2 表示 从 i 出发 到达 n 的最少初始值
	for(int i=n-1; i>=1; --i)
		f2[i]=min(f2[i+1]+a[i]-nxt[i],a[i]-nxt[i]);
	for(int i=1; i<=n; ++i)
		f2[i]*=-1;
	
	//顺时针
	for(int i=1; i<=n; ++i) {
		if(f2[i] > 0) continue; 
		ll tmp1=sum_jia[n] - sum_jia[i-1];
		ll tmp2=sum_jian[n] - sum_jian[i-1];
		ll zzz=tmp1-tmp2;
		if(zzz < f1[i]) continue;
		is_ok[i]=1;
	}
	
	
	//清空 
	memset(f1,0,sizeof(f1));
	memset(f2,0,sizeof(f2));
	
	
	//f1 表示 从 n 出发 到达 i 的最少初始值
	sheng=0,ma=-inf;
	for(int i=n-1; i>=1; --i) {
		sheng+=a[i+1]-nxt[i];
		ma=max(ma,-sheng);
		f1[i]=ma;
	}

	//f2 表示 从 i 出发 到达 1 的最少初始值
	for(int i=2; i<=n; ++i)
		f2[i]=min(f2[i-1]+a[i]-nxt[i-1],a[i]-nxt[i-1]);
	for(int i=1;i<=n;++i)
		f2[i]*=-1;

	//逆时针
	for(int i=1; i<=n; ++i) {
		if(f2[i] > 0) continue;
		ll tmp1=sum_jia[i];
		ll tmp2=sum_jian[i-1];
		ll zzz=tmp1-tmp2;
		if(zzz-nxt[n] < max(f1[i],0LL)) continue;
		is_ok[i]=1;
	}

	//输出 
	for(int i=1; i<=n; ++i) {
		if(is_ok[i]) puts("TAK");
		else puts("NIE");
	}
	return 0;
}

原文地址:https://www.cnblogs.com/dsrdsr/p/9768073.html