列表

详情


NC50531. 旅行问题

描述

John打算驾驶一辆汽车周游一个环形公路。公路上总共有n车站,每站都有若干升汽油(有的站可能油量为零),每升油可以让汽车行驶一千米。John必须从某个车站出发,一直按顺时针(或逆时针)方向走遍所有的车站,并回到起点。在一开始的时候,汽车内油量为零,John每到一个车站就把该站所有的油都带上(起点站亦是如此),行驶过程中不能出现没有油的情况。
任务:判断以每个车站为起点能否按条件成功周游一周。

输入描述

第一行是一个整数n,表示环形公路上的车站数;
接下来n行,每行两个整数p_i,d_i,分别表示表示第i号车站的存油量和第i号车站到下一站的距离。

输出描述

输出共n行,如果从第i号车站出发,一直按顺时针(或逆时针)方向行驶,能够成功周游一圈,则在第i行输出TAK,否则输出NIE。

示例1

输入:

5
3 1
1 2
5 2
0 1
5 4

输出:

TAK
NIE
TAK
NIE
TAK

原站题解

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

C++(g++ 7.5.0) 解法, 执行用时: 37ms, 内存消耗: 4600K, 提交时间: 2023-03-17 17:07:17

#include<bits/stdc++.h>
using namespace std;
const int N=1e6+4;
long long s[2*N];
bool vs[N];
int p[N],d[N],a[2*N],q[2*N];
int main()
{
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++) 
    {
        scanf("%d%d",&p[i],&d[i]);
        a[i]=a[i+n]=p[i]-d[i];
    }
    int hh=1,tt=1;
    for(int i=1;i<=2*n;i++)
    {
        s[i]=s[i-1]+a[i];
        while(hh <= tt && i - q[hh] >= n)hh++;
        while(hh <= tt && s[i] <= s[q[tt]])
            tt--;
        q[++tt] = i;
        if(i>=n&&s[q[hh]]>=s[i-n])
            vs[i-n+1]=true;
        
    }
    for(int i=1;i<n;i++)
        a[i]=a[i+n]=p[n-i+1]-d[n-i];
    a[n]=p[1]-d[n];
    hh = 1, tt = 0;
    for(int i=1;i<=2*n;i++)
    {
        s[i]=s[i-1]+a[i];
        while(hh <= tt && i - q[hh] >= n)hh++;
        while(hh <= tt && s[i] <= s[q[tt]])
            tt--;
        q[++tt] = i;
        if(i>=n&&s[q[hh]]>=s[i-n])
            vs[2*n-i]=true;
    }
    for(int i=1;i<=n;i++) 
        if(vs[i])
            puts("TAK");
        else
            puts("NIE");
    return 0;
}

C++11(clang++ 3.9) 解法, 执行用时: 31ms, 内存消耗: 3916K, 提交时间: 2020-08-04 09:12:40

#include<bits/stdc++.h>
#define mp make_pair
using namespace std;
const int N=3e6+10;
bool ans[N][2];
int n,p[N],d[N];
long long dp[6000000];
deque<long long>q;
void around(int id){
	for(int i=1;i<n;i++){
		dp[i+n]=dp[i],dp[i]+=dp[i-1];
		while(!q.empty()&&dp[i]<q.back())
			q.pop_back();
		q.push_back(dp[i]);
	}for(int i=0,j=n;i<n;i++,j++){
		dp[j]+=dp[j-1];
		while(!q.empty()&&dp[j]<q.back())
			q.pop_back();
		q.push_back(dp[j]);
		if(i&&q.front()==dp[i])q.pop_front();
		if(q.front()>=dp[i])ans[i][id]=true;
	}q.clear();
}int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++) 
		scanf("%d%d",p+i,d+i),dp[i]=p[i]-d[i];
	around(0),d[0]=d[n];
	for(int i=1;i<=n;i++)
		dp[i]=p[n+1-i]-d[n-i];
	around(1); 
	for(int i=0;i<n;i++)
		puts((ans[i][0]||ans[n-i-1][1])?"TAK":"NIE");
	return 0;
}

上一题