链接:http://codeforces.com/gym/101775/problem/J
思路:https://www.jianshu.com/p/83ea421664fb
对于 差分完的数组B 其实如果 bi >0 表示可以在i位置打出去bi个顺子并且i作为顺子的第一张牌, 如果bi <0 表示必须在将 i-1
位置当做末尾并且打出去 abs(bi) 次顺子。
那么就树状数组维护一下子。
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 2e5+5;
ll c[N];
ll a[N];
ll b[N];
int n;
int lowbit(int x)
{
return x&(-x);
}
void update(int x,ll val)
{
for(;x<=n+2;x+=lowbit(x))
{
c[x]+=val;
}
}
ll query(int x)
{
ll sum=0;
for(;x>0;x-=lowbit(x))
{
sum+=c[x];
}
return sum;
}
int main()
{
int T;
scanf("%d",&T);
int kk=0;
while(T--)
{
scanf("%d",&n);
a[0]=a[n+1]=0;
for(int i=0;i<=n+5;i++) c[i]=0;
for(int i=1;i<=n;i++){
scanf("%lld",&a[i]);
}
for(int i=1;i<=n+1;i++) b[i]=a[i]-a[i-1];
/*
for(int i=1;i<=n+1;i++) cout<<b[i]<<" ";
cout<<endl;
*/
ll sum=0;
int f=0;
for(int i=1;i<=n+1;i++)
{
if(b[i]==0) continue;
if(b[i]>0){
update(i,b[i]);
}
else if(b[i]<0)
{
ll xx=query(i-3);
xx-=sum;
//cout<<"xx "<<xx<<endl;
if(xx>=abs(b[i])){
sum+=abs(b[i]);
continue;
}
else{
f=1; break;
}
}
}
if(f) printf("Case #%d: No\n",++kk);
else printf("Case #%d: Yes\n",++kk);
}
return 0;
}
/*
1
7
1 2 3 5 3 2 1
1
14
1 2 3 5 3 2 1 1 2 3 5 3 2 1
100
5
1 2 3 4 5
5
1 0 1 0 1
*/