POJ 2566バウンドが見つかりました(接頭辞と定規)


トピックへのリンクトピックの主な考え方:絶対値が指定された数値に最も近い長さ\(n \)のシーケンスの範囲を見つける必要があるたびに、\(m \)クエリがあります。(この質問にはspjがあり、複数のソリューションがある場合は、1つだけ出力します)。   質問は規則決定の質問のように見えますが、シーケンスには正と負の両方の数があるため、間隔の合計は単調ではなく、直接の規則決定は明らかに不可能です。しかし、問題は間隔に関するものであるため、シーケンスを単調にする方法があります。シーケンスの接頭辞の合計を取り、接頭辞の合計を小さいものから大きいものに並べ替えると、接頭辞とシーケンスの差は単調になります。昇順に、及びプレフィックスの場合(a_iを\)\\(a_j \)、\ (I <J \)、\ (J \)より大きい\(I \)は小さく、より多くの差であります大きいほど、つまり、区間合計の絶対値が大きくなります。   ただし、ルーラーの初期位置が選択されていることに注意してください。接頭辞とシーケンスが小さいものから大きいものへと並べ替えられていると仮定すると、負の接頭辞とシーケンスでは、最小の接頭辞と開始規則を採用する必要があります。そのため、\(r \)が大きいほど、その規則の間隔合計の絶対値になります。大きい、\(Lは\)小さく、足がかかり、その部分取ら足の小さな絶対値(\ 0)\、それがtake-足に最初の位置から開始位置を示します。正の接頭辞とシーケンスの場合、ルーラー\(0 \)から取得する必要があります。これは、ルーラーが最初の位置から特定の位置まで取得されることを示します。負の数列も\(0 \)からの場合

ルーラーが開始すると、\(r \)が大きいほど、間隔の合計の絶対値は小さくなり、\(l \)が大きいほど、セル間の合計の絶対値は大きくなります。したがって、並べ替えの前に\(0 \)要素をプレフィックスとシーケンスに追加するたびに、負の数があるかどうかに関係なく、プレフィックスとシーケンスを一貫させることができます。説明するのは難しいです。理解できない場合は、コードを見てください。

const int maxn = 1e5+10;
int n, m;
struct PRE {
	int num;int val;
	bool operator < (const PRE &a) const {
		return val<a.val;
	}
} pre[maxn];
int main(void) {
	while(~scanf("%d%d", &n, &m) && (n||m)) {
		pre[0].val = pre[0].num = 0;
		for (int i = 1; i<=n; ++i) {
			scanf("%d", &pre[i].val);
			pre[i].val+=pre[i-1].val; pre[i].num = i; 
		}
		sort(pre, pre+n+1);
		while(m--) {
			int t, l = 0, r = 1, ans, ansl, ansr, minn = INF;
			scanf("%d", &t);
			while(r<=n) {
				int d = abs(pre[r].val - pre[l].val);
				if (minn >= abs(d-t)) {
					minn = abs(d-t);
					ans = d;
					ansl = pre[l].num;
					ansr = pre[r].num;
				}
				if (d<=t) ++r;
				else ++l;
				if (l==r) ++r; //避免上一步出现l==r然后minn因此更新成0的情况,前缀和求区间相减的两个前缀和必不相等,除非是空区间
			}
			if (ansl>ansr) swap(ansl, ansr);
			printf("%d %d %d\n", ans, ansl+1, ansr); 
		}
	}
    return 0;
}

おすすめ

転載: www.cnblogs.com/shuitiangong/p/12739951.html