【NKOJ3545】单调队列
单调队列是也。
NKOJ3545
我们发现,本题的时间复杂度必须是线性的,时间复杂度只能是 O(NT)
于是我们考虑如果如果原函数是单调的,前缀和也是单调的,那么本题就很好搞了。
在这种特殊情况下,我们利用单调队列,一个指向开头一个指向末尾。
由于sum[r]-sum[l]>=p时,向右移动r不会对答案进行更新
由于sum[r]-sum[l]<p时,向右移动l不会对答案更新,那么这个就很好,显然满足单调队列,那么我们就一直将R右移将L右移,始终满足sum[r]-sum[l]>=p (当sum[r]-sum[l+1]<p特判一下)
可是原数列中有负数怎么搞?不满足单调性啊啊啊?
我们开个结构体,将前缀和排个序就可以满足单调性了呀!
code:
#include<stdio.h>
#include<bits/stdc++.h>
#define int long long
using namespace std;
struct node
{
int sum,x;
}z[100005];
int t;
int n;
int X;
bool cmp(node aa,node bb)
{
return aa.sum<bb.sum;
}
int ansl,ansr,ans,L;
int anz;
void change(int l,int r)
{
int zhi = z[r].sum - z[l].sum ;
int L = min(z[l].x,z[r].x);
int R=max(z[l].x,z[r].x);
L++;
if(abs(X-zhi)>ans) return ;
if(abs(X-zhi)==ans)
{
if(L<ansl)
{
ansl = L; ansr = R; anz =zhi;
}
else if(L==ansl&&R<ansr)
{
ansr = R; anz = zhi;
}
return;
}
ans = abs(X-zhi);
ansl = L;
ansr = R;
anz = zhi;
}
void solve()
{
ans = 0x3f3f3f3f;
L = 1;
for(int i=2;i<=n;i++)
{
while( L<i-1&&z[i].sum-z[L+1].sum-X>=0 ) change(L,i),++L;
if(L<i-1) change(L+1,i); change(L,i);
}
change(L,n);
printf("%lld %lld %lld\n",anz,ansl,ansr);
}
main()
{
scanf("%lld%lld",&n,&t);
for(int i=1;i<=n;i++)
{
scanf("%lld",&z[i].sum); z[i].sum = z[i-1].sum+z[i].sum;
z[i].x = i;
}
z[++n].x = 0; z[n].sum = 0;
sort(z+1,z+1+n,cmp);
for(int i=1;i<=t;i++) scanf("%lld",&X),solve();
}

浙公网安备 33010602011771号