第一行照例留给本鸽子精咕咕咕。
尺取法:
1.取数组的一段,即先保存数组的一对下标,根据要求左右移动,不停更新数组前后指针,获取区间值,最终得到答案。
2.多用于求给定的一组数据中,满足某个条件的最优连续子序列。
3.尺取法通常需要对数据进行预处理,方便快速判断(多为预处理前缀和。
4.尺取法必须是找到单调性。
例题:1.POJ3061
思路:尺取模板题,就是尺取的思路。
下附代码:
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#define ll long long
#define inf 0x3f3f3f3f
using namespace std;
//尺取
int main()
{
int t;
int a[100005];
scanf("%d",&t);
while(t--)
{
int n,m;
int ans = 0;
int res = inf;
int sum = 0;
scanf("%d%d",&n,&m);
for(int i = 0; i < n; ++i)
{
scanf("%d",&a[i]);
ans += a[i];
}
if(ans < m)
{
printf("0\n");
continue;
}
else
{
int l = 0, r = 0;
while(true)
{
while(r<n && sum<m)
sum += a[r++];
if(sum < m) break;
res = min(res, r-l);
sum -= a[l++];
}
printf("%d\n",res);
}
}
return 0;
}
2.POJ2566
思路:这道题的不同之处在于,数值可以为正也可以为负。
我就不明白了怎么我用结构体就死活A不了呢,不都是存前缀和和下标么!
这是wa的代码我不管我就是要贴上来qwq求大神指点一二
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#define ll long long
#define inf 0x3f3f3f3f
using namespace std;
struct qwq
{
ll sum;
int xb;
} q[101005];
bool com(qwq x,qwq y)
{
if(x.sum < y.sum)
return true;
else if(x.sum == y.sum)
return x.xb<y.xb;
else
return false;
}
ll qabs(ll y)
{
return y>0?y:-y;
}
int main()
{
int n,k;
q[0].sum = 0;
q[0].xb = 0;
while(scanf("%d%d",&n,&k)!=EOF)
{
for(int i = 1; i <= n; ++i)
{
int a;
scanf("%d",&a);
q[i].sum = q[i-1].sum+a;
q[i].xb = i;
}
sort(q,q+n+1,com);
while(k--)
{
int l = 0, r = 1;
int res = inf;
int qs,zz;
ll ans;
ll t;
scanf("%lld",&t);
while(r <= n)
{
ll x = q[r].sum-q[l].sum;//排序后用大的减去小的已经他体现了绝对值了
if(qabs(x-t) < res)
{
res = qabs(x-t);
ans = x;
qs = q[l].xb;
zz = q[r].xb;
}
if(x > t) l++;
else if(x < t) r++;
else break;
if(l == r) r++;
}
if(qs > zz) swap(qs,zz);
printf("%lld %d %d\n",ans,qs,zz);
}
}
return 0;
}
求指点qwq