题目
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;
}