洛谷CF429Dトリッキー機能

洛谷CF429Dトリッキー機能

トピック:

ソリューション:

  • 人々の話題をすることを意図しています。
  • [1]、[2]、...、[n]はA与えられた配列
  • 函数 f(i, j) = (i - j) ^ 2 + (a[i+1] + a[i+2] + … + a[j]) ^ 2
  • Fの最小化。N≤100000

  • []配列とプレフィックスにSUM []を提供しました。
  • 次いで、F(i、j)はF(i、j)は=(I - J)のように書き換えることができる^ 2 +(和[J] - 和[I])^ 2
  • これではなく、その距離の式それ?
  • その距離の点の正方形(I、和[I])と点(J、和[J])の。
  • だから、この質問は、変換されたn平面上の点は、最寄りのポイントのペアを見つける、となりました。

  • パーティションがTに最も近い点を見つけることは注目に値します 即ち
for(int i = l; i <= r; i++)
    {
        int v = a[i].x - a[mid].x;
        if(v < d)
            t[++cnt] = i;
    }
sort(t + 1, t + 1 + cnt, cmp2);
for(int i = 1; i < cnt; i++)
    for(int j = i + 1; j <= cnt; j++)
    {
        int v = a[t[j]].y - a[t[i]].y;
        if(v >= d) break;
        else d = min(d, cal(t[i], t[j]));
    }
  • 次のようにコードのこの作品はアウトに、変更する必要があります。
for(int i = l; i <= r; i++)
    {
        int v = a[i].x - a[mid].x;
        if(v * v < d) //改动了这里
            t[++cnt] = i;
    }
sort(t + 1, t + 1 + cnt, cmp2);
for(int i = 1; i < cnt; i++)
    for(int j = i + 1; j <= cnt; j++)
    {
        int v = a[t[j]].y - a[t[i]].y;
        if(v * v >= d) break; //改动了这里
        else d = min(d, cal(t[i], t[j]));
    }
  • 個人的に私は変更は原則的にもっともらしいではないと思われます。
  • どのように正しすぎこんにゃく変更後の証明を理解していません。
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#define N 100005
#define inf 0x7fffffff
#define int long long
using namespace std;

struct A {int x, y;} a[N];
int sum[N], t[N];
int n;

int read()
{
    int x = 0, f = 1; char c = getchar();
    while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();}
    while(c >= '0' && c <= '9') {x = x * 10 + c - '0'; c = getchar();}
    return x *= f;
}

bool cmp1(A u, A v) {return u.x < v.x;}
bool cmp2(int u, int v) {return a[u].y < a[v].y;}

int cal(int u, int v)
{
    int v1 = (a[u].x - a[v].x) * (a[u].x - a[v].x);
    int v2 = (a[u].y - a[v].y) * (a[u].y - a[v].y);
    return v1 + v2;
}

int fun(int l, int r)
{
    if(l == r) return inf;
    if(l + 1 == r) return cal(l, r);
    int mid = (l + r) >> 1, cnt = 0;
    int d = min(fun(l, mid), fun(mid + 1, r));
    for(int i = l; i <= r; i++)
    {
        int v = a[i].x - a[mid].x;
        if(v * v < d)
            t[++cnt] = i;
    }
    sort(t + 1, t + 1 + cnt, cmp2);
    for(int i = 1; i < cnt; i++)
        for(int j = i + 1; j <= cnt; j++)
        {
            int v = a[t[j]].y - a[t[i]].y;
            if(v * v >= d) break;
            else d = min(d, cal(t[i], t[j]));
        }
    return d;
}

signed main()
{
    cin >> n;
    for(int i = 1; i <= n; i++)
    {
        int val = read();
        sum[i] = sum[i - 1] + val;
        a[i].x = i, a[i].y = sum[i];
    }
    sort(a + 1, a + 1 + n, cmp1);
    cout << fun(1, n);
    return 0;
}

おすすめ

転載: www.cnblogs.com/BigYellowDog/p/11628318.html