トピックリンクバインドが見つかりました
題名
N個の整数があり、負または正の場合があります。数値tを与え、連続間隔の合計の絶対値がtに最も近くなるように、N個の数値から連続間隔を見つけ、連続間隔の合計と間隔の上限と下限の絶対値の合計を見つけます。
アイデア
- ルーラーテイクメソッド
名前が示すように、ルーラーのようなセグメントをテイクします。ルーラーテイクメソッドは通常、サブスクリプトのペアを配列、つまり選択した間隔の左右のエンドポイントに保存し、実際の状況に応じてインターバルの左右のエンドポイントを継続的に進めて答えを取得します。 - ルーラーメソッドはいつ使用できますか?
私自身の理解は次のとおりです。答えは連続間隔または連続間隔です(状況を満たすために複数の間隔がある場合があります。質問では最適な間隔を見つける必要があります)。通常、間隔は配列の左端から動的です。右端に移動します。間隔の範囲が拡大する(右の終点が右に移動する)ほど、回答に近づき、間隔が縮小する(左の終点が右に移動する)ほど、回答は遠くなります。また、現在の間隔の状態に応じて、左端点と右端点のどちらが右にシフトしているかを判断できます。 - 例
間隔の開始と終了を繰り返し進めて、条件を満たす最小間隔を見つける方法をルーラー法と呼びます。 - この質問で
は、配列内の数値が正または負であるため、ルーラーメソッドは使用できません。ルーラー方式を使用し、最適な間隔の上限と下限を見つけるために、最初に接頭辞の合計を取得してから、接頭辞の合計に従って並べ替えることができます。並べ替えの際、接頭辞の合計と添え字は、構造の並べ替え用の構造に格納されます。 。間隔とsum <tの場合は、右端点を右に移動します。sum> tの場合は、左端点を右に移動して、合計がtにできるだけ近くなるようにします。間隔が動的に変換されると、回答を更新できます。
コード
//#pragma GCC optimize(2)
//#include<bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<string>
#include<vector>
using namespace std;
typedef long long ll;
typedef unsigned long ul;
typedef unsigned long long ull;
#define pi acos(-1.0)
#define e exp(1.0)
#define pb push_back
#define mk make_pair
#define fir first
#define sec second
#define scf scanf
#define prf printf
typedef pair<int,int> pa;
const int INF=0x3f3f3f3f;
const int MAX_N=1e5+7;
int N,K,T;
int num[MAX_N];
struct node{
int s,pos;
bool operator<(const node &a)const{
//从小到大排序
if(s!=a.s)
return s<a.s;
return pos<a.pos;
}
};
vector<node>V;
void do_(int t){
int L=0,R=1,aL,aR,minn=INF,sum=0,ans;
while(L<=R&&R<V.size()){
int sum=V[R].s-V[L].s;
if(abs(sum-t)<minn){
minn=abs(sum-t);
ans=sum;
aR=max(V[R].pos,V[L].pos);
aL=min(V[R].pos,V[L].pos);
}
if(sum<t)
R++;
else if(sum>t)
L++;
else
break;
if(L==R){
R++;
}
}
prf("%d %d %d\n",ans,aL+1,aR);
}
int main()
{
// freopen(".../.txt","w",stdout);
// freopen(".../.txt","r",stdin);
// ios::sync_with_stdio(false);
int i,j,k;
while(~scf("%d %d",&N,&K)&&(N||K)){
V.clear();
for(i=1;i<=N;i++){
scf("%d",&num[i]);
}
int tmp=0;
V.pb({
0,0});
for(i=1;i<=N;i++){
tmp=tmp+num[i];
V.pb({
tmp,i});
}
sort(V.begin(),V.end());
for(i=0;i<K;i++){
scf("%d",&T);
do_(T);
}
}
return 0;
}