http://www.elijahqi.win/archives/2751
一列数 给定起始位置两个人一个人只能向左移动 一个人只能向右移动 然后要求满足(px,py]这个区间的所有数和都<=0 大概n^2dp 写一下水30
但是正解贪心 考场上很多巨佬乱搞ac 我还是没有吃一堑长一智 在thuwc吃的亏 现在也没记住 既然会写namespace了也不写完部分分之后暴力贪心瞎搞一下 后来还剩20分钟觉得t1暴力可搞因为太着急了 就写错了两个变量白丢20分
这题贪心做首先 预处理前缀和 可以将题目的限制条件变成sum[i]-sum[j]>=0
一开始贪心匹配 根据这个式子暴力扩展即可
然后就需要根据之前预处理的前缀最大值最小值 还有后缀最大值最小值来处理了
if (mx1[x-1]<mx2[y+1]&&mn1[x-1]<mn2[y+1]) {puts("No");ok=1;break;}
这句话神坑 结束第一部分扩展之后第二部分的扩展注意这句话得加上 因为当且仅当满足这个条件时我无法再继续扩展了 否则还是有可能贪心继续扩展
#include<cstdio>
#include<algorithm>
#define ll long long
#define rg register
#define N 110000
#define inf 1LL<<60
using namespace std;
inline char gc(){
static char now[1<<16],*S,*T;
if (T==S){T=(S=now)+fread(now,1,1<<16,stdin);if (T==S) return EOF;}
return *S++;
}
inline ll read(){
ll x=0,f=1;char ch=gc();
while(ch<'0'||ch>'9'){if (ch=='-')f=-1;ch=gc();}
while(ch<='9'&&ch>='0') x=x*10+ch-'0',ch=gc();
return x*f;
}
ll a[N],mn1[N],mx1[N],mn2[N],mx2[N];int n,k;
int main(){
freopen("t3.in","r",stdin);
int T=read();mn1[0]=inf;mx1[0]=-inf;
while(T--){
n=read();k=read();for (rg int i=1;i<=n;++i) a[i]=a[i-1]+read();mn2[n+1]=inf;mx2[n+1]=-inf;
for (rg int i=1;i<=n;++i) mn1[i]=min(mn1[i-1],a[i]),mx1[i]=max(mx1[i-1],a[i]);
for (rg int i=n;i;--i) mn2[i]=min(mn2[i+1],a[i]),mx2[i]=max(mx2[i+1],a[i]);
int x=k,y=k;bool flag=1,ok=0;
while(flag){
flag=0;
for (rg int i=x-1;i&&a[i]>=a[y];--i) if (a[i]>=a[x]) {flag=1;x=i;break;}
for (rg int i=y+1;i<=n&&a[i]<=a[x];++i) if (a[i]<=a[y]) {flag=1;y=i;break;}
}if (a[y]>mn1[x]||a[x]<mx2[y]) {puts("No");continue;}
while(x!=1||y!=n){
if (x==1) {while(y<n&&a[y+1]<=a[x]) ++y;break;}
if (y==n) {while(x>1&&a[x-1]>=a[y]) --x;break;}
if (x==1&&y==n) {puts("Yes");ok=1;break;}
if (x==1||y==n) {
if (x==1)++y;else if (y==n) --x;if (a[x]<a[y]) {puts("No");ok=1;break;}
}else{
if (mx1[x-1]<mx2[y+1]&&mn1[x-1]<mn2[y+1]) {puts("No");ok=1;break;}
if (mx1[x-1]>=mx2[y+1]) --x;else ++y;
}
}if (!ok) x==1&&y==n?puts("Yes"):puts("No");
}
return 0;
}