確定了起點和方向之後,旅行的過程就確定了,到達i點的花費<=到i點之間的油料數量就是題目的限制條件.
由於是繞圈問題,我們可以把序列複製相接,轉化成序列上的問題.
設
移項得到:
那麼只要保證
問題就轉化爲了求區間最值問題,根據起點的移動規律,可以確定每次
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const int M=2e6+5;
int d[M],p[M],n,Q[M],id[M];
ll sum[M],dis[M];
bool f[M];
inline void rd(int &res){
res=0;char c;
while(c=getchar(),c<48);
do res=(res<<1)+(res<<3)+(c^48);
while(c=getchar(),c>=48);
}
void solve(int s){
int i,j,k;
sum[0]=0;
for(i=1;i<=n*2;i++){
sum[i]=sum[i-1]+p[i-1];//sum[i]表示從1到i能得到的油量,不包括i
dis[i]=dis[i-1]+d[i+s];//從1到i的距離和
}
/*
for i
j->[i+1,i+n] sum[j]-sum[i]>=dis[j]-dis[i]
sum[j]-dis[j]>=sum[i]-dis[i].
Min(sum[j]-dis[j])>=sum[i]-dis[i]
Push k -> pop val[j]>=val[k]
*/
int L=0,R=-1;
for(i=2;i<=n+1;i++){
while(R>=L&&sum[Q[R]]-dis[Q[R]]>=sum[i]-dis[i])R--;
Q[++R]=i;
}
for(i=1;i<=n;i++){//判斷i點是否可行
while(L<=R&&Q[L]<i+1)L++;
if(L<=R){
k=Q[L];
if(sum[k]-dis[k]>=sum[i]-dis[i])f[id[i]]=true;
}
while(R>=L&&sum[Q[R]]-dis[Q[R]]>=sum[i+n+1]-dis[i+n+1])R--;
Q[++R]=i+n+1;
}
}
int main(){
int i,j,k;
rd(n);
for(i=1;i<=n;i++){
id[i]=i;
rd(p[i]),rd(d[i]);
p[i+n]=p[i];
d[i+n]=d[i];
}
solve(-1);
for(i=1;i<=n;i++){
swap(d[i],d[2*n-i+1]);
swap(p[i],p[2*n-i+1]);
id[i]=n-i+1;
}
solve(0);
for(i=1;i<=n;i++){
if(f[i])puts("TAK");
else puts("NIE");
}
return 0;
}