P7635 [COCI2010-2011#5] DVONIZ 题解
tongzhenxuan · · 题解
思路解析:
1.考虑暴力算法 O(n^3) 。
枚举左右端点,遍历判断是否合法。最多只能拿
2.暴力加上前缀和优化 O(n^2) 。
可以省去遍历所需复杂度。能拿到
3.枚举中间点加二分答案 O(nlogn) 。
因为题目中说每个元素的值都为正整数。
可以考虑枚举中间点
即
len=min(r-mid,mid-l+1);
tot[mid-len+1]=max(2*len,tot[mid-len+1]);
注:
但这样的做法是不完全的,有部分端点的值被更新到了,但是有一些端点没有被更新。考虑到将一个合法的区间去掉头尾两个元素,还是成立的,可以推出:
tot[i]=max(tot[i],tot[i-1]-2);
最后这里要更新一边才能得到最终答案。
这样的做法可以拿到
4.枚举中间点加尺取法 O(n) 。
形同第三条,也是枚举
code:
#include<bits/stdc++.h>
#define N 3000005
using namespace std;
int n,k;
int a[N],s[N],tot[N];
int main()
{
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
s[i]=s[i-1]+a[i];
}
int len,head=1,tail=1;
for(int mid=1;mid<=n;mid++)
{
while(s[mid]-s[head-1] > k) head++;
while(s[tail+1]-s[mid] <= k && tail < n) tail++;
len=min(tail - mid , mid - head + 1);
tot[mid-len+1]=max(tot[mid-len+1],len*2);
}
for(int i=1;i<=n;i++)
tot[i]=max(tot[i],tot[i-1]-2);
for(int i=1;i<=n;i++)
printf("%d\n",tot[i]);
return 0;
}