CF1491C Pekora and Trampoline
Priori_Incantatem · · 题解
原题链接 洛谷链接
题目翻译
我的Blog
题意就不赘述了
考虑贪心,显然每轮最开始调到第一个
定义
那么,我们贪心的从
由于最终这个蹦床的
在考虑完对后面蹦床的贡献后,我们考虑蹦床
总时间复杂度
PS: 为了美观并且方便理解,这里只提供未开 long long 的代码
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int Maxn=5010;
int n,ans;
int a[Maxn],sum[Maxn];
inline int lowbit(int x)
{
return x&(-x);
}
void modify(int x,int v)
{
if(x>n || x<1)return;
while(x<=n)
{
sum[x]+=v;
x+=lowbit(x);
}
}
int query(int x)
{
int ret=0;
while(x)
{
ret+=sum[x];
x-=lowbit(x);
}
return ret;
}
inline int read()
{
int s=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0' && ch<='9')s=(s<<3)+(s<<1)+(ch^48),ch=getchar();
return s*w;
}
int main()
{
// freopen("in.txt","r",stdin);
int T=read();
while(T--)
{
n=read();
for(int i=1;i<=n;++i)
a[i]=read(),sum[i]=0;
for(int i=1;i<=n;++i)
{
int tmp=a[i]-query(i);
if(tmp>1)
ans+=tmp-1;
if(a[i]>1)
modify(i+2,1),modify((i+a[i])+1,-1);
if(tmp<1ll)
modify(i+1,1-tmp),modify(i+2,tmp-1);
}
printf("%lld\n",ans);
ans=0;
}
return 0;
}
Update: 03.04: 发现这个做法好像可以优化到
我们把树状数组换成差分,但看上去似乎差分只能支持区间修改,不支持在线的查询。
但是,可以发现这些操作具有一些良好的性质:
- 查询操作是从前往后依次查询的,也就是
1\dots n 的位置都被挨个查了一遍。 - 当我们查询完位置
i ,之后的所有修改都不会跟1\dots i 有关系。
那么,我们可以在枚举蹦床的时候维护差分数组,也就是 sum[i]+=sum[i-1]。这样,单次查询和修改就都是
总时间复杂度
代码仍旧未开 long long
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int Maxn=5010;
int n,ans;
int a[Maxn],sum[Maxn];
inline int read()
{
int s=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0' && ch<='9')s=(s<<3)+(s<<1)+(ch^48),ch=getchar();
return s*w;
}
int main()
{
// freopen("in.txt","r",stdin);
int T=read();
while(T--)
{
n=read();
for(int i=1;i<=n;++i)
a[i]=read(),sum[i]=0;
for(int i=1;i<=n;++i)
{
sum[i]+=sum[i-1];
int tmp=a[i]-sum[i];
if(tmp>1)
ans+=tmp-1;
if(a[i]>1)
{
if(i+2<=n)
sum[i+2]++;
if(i+a[i]+1<=n)
sum[i+a[i]+1]--;
}
if(tmp<1)
{
if(i+1<=n)
sum[i+1]+=(1-tmp);
if(i+2<=n)
sum[i+2]-=(1-tmp);
}
}
printf("%lld\n",ans);
ans=0ll;
}
return 0;
}