题解 玩游戏
考场上用了一个平均 \(O(n)\) ,最坏 \(O(n^2)\) 的方法过掉了
先说说这个方法:
取一个左指针,一个右指针,初始位置都在 \(k\)
每次让右指针在满足 \(tot \leqslant 0\) 的前提下尽量右移
当发现右指针移动不了时,尝试把左指针左移一位
如果发现移过去会让 \(tot > 0\) ,就不断左移右指针到第一个可以让左指针左移的位置
如果没有这样的位置,puts("No");
如果有,就移过去
重复上述过程直到两指针均到达边界
但可以构造数据让右指针的移动是 \(n^2\) 级别的
其实可以用主席树处理退化,复杂度严格 \(nlogn\)
但战神试了发现慢了6倍
至于题解做法:
从位置 \(k\) 向左右两边分别做前缀和
发现如果能移到一个前缀和更小的地方就一定会移
重复此过程,两指针均会移到前缀和最小的位置
然后应该是可以可以把数组倒过来,从两边向位置 \(k\) 走
如果也能走到最小值的位置即为合法
Code:
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 100010
#define ll long long
#define fir first
#define sec second
#define make make_pair
#define reg register int
//#define int long long
char buf[1<<21], *p1=buf, *p2=buf;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf, 1, 1<<21, stdin)), p1==p2?EOF:*p1++)
inline ll read() {
ll ans=0, f=1; char c=getchar();
while (!isdigit(c)) {if (c=='-') f=-f; c=getchar();}
while (isdigit(c)) {ans=(ans<<3)+(ans<<1)+(c^48); c=getchar();}
return ans*f;
}
int n, k;
ll a[N], sum[N];
namespace force{
queue< pair<int, int> > q;
pair<int, int> t;
void solve() {
while (q.size()) q.pop();
q.push(make(k, k));
while (q.size()) {
t=q.front(); q.pop();
if (t.fir==1 && t.sec==n && sum[t.sec]-sum[t.fir]<=0) {puts("Yes"); return ;}
if (t.fir>1 && sum[t.sec]-sum[t.fir-1]<=0) {
if (t.fir-1==1 && t.sec==n) {puts("Yes"); return ;}
q.push(make(t.fir-1, t.sec));
}
if (t.sec<n && sum[t.sec+1]-sum[t.fir]<=0) {
if (t.fir==1 && t.sec+1==n) {puts("Yes"); return ;}
q.push(make(t.fir, t.sec+1));
}
}
puts("No");
}
}
namespace task1{
void solve() {
int l=k, r=k;
ll tot=0;
while (l>1 || r<n) {
//cout<<"loop"<<endl;
while (r<n && tot+a[r+1]<=0) tot+=a[r+1], ++r;
//cout<<"r: "<<r<<endl;
if (l>1) {
if (tot+a[l]<=0) tot+=a[l], --l;
else {
while (r>k) {
tot-=a[r], --r;
if (tot+a[l]<=0) {tot+=a[l], --l; goto jump;}
}
puts("No"); return ;
jump: ;
}
//cout<<"now: "<<l<<' '<<r<<' '<<tot<<endl;
}
else if (r<n) {puts("No"); return ;}
}
//cout<<l<<' '<<r<<' '<<tot<<endl;
puts("Yes");
//if (l==1 && r==n && tot<=0) puts("Yes");
//else puts("error");
}
}
signed main()
{
int T;
T=read();
while (T--) {
n=read(); k=read();
for (reg i=1; i<=n; ++i) a[i]=read(), sum[i]=sum[i-1]+a[i];
//force::solve();
task1::solve();
}
return 0;
}