CF1635F. Closest Pair (2800) (贪心,离线,树状数组)

https://codeforces.com/contest/1635/problem/F
题意
给出3e5个点,每个点有一个权值\(wi\), 定义两个点的权值为\(|(x_{i} - x_{j}) * (w_{i} + w_{j})|\),有3e5个询问,每次询问\([l, r]\)区间中两点的最小权值,(xi和wi都是递增给出的)
思路

  • 性质: 若两个点i,j要成为Closest Pair,则他们中间不能有小于 max(wi, wj) 的点,否则中间这个点和 min(wi, wj) 可以形成更优的答案。
  • 对于一个点xi,他只会和前面离他较近且比他大的①或者第一个比他小的②组成CP。和xi配对的点不会和后面加进来的组,因为wi是递增给出的,这不满足上面性质
  • 我们用单调栈找出所有对,计算一对的权值按xi离线,把询问按r离线。
  • 我们用树状数组找区间最小值时候需要l到r (等价l到n)的最小值,需要后缀最值,但是树状数组只能维护前缀最值,所以把下标取负+n+1,正常操作就是后缀最值了。
    image
    image
#include <bits/stdc++.h>
using namespace std;
//#pragma GCC optimize(2);
#define IOS ios::sync_with_stdio(false) ,cin.tie(0), cout.tie(0);
const double PI = acos(-1.0);
typedef long long ll;
const int N = 5e5+ 5 ;//////
const int M = 1e5 + 5;
const double eps =1e-13;
const ll mod =  998244353;
const int INF = 0x3f3f3f3f;
const ll LNF = 0x3f3f3f3f3f3f3f3fll;
typedef pair<int,int> PII;
int n, m, a[N], b[N], pre[N], pos[N], ans[N];
struct chimer{
    int l, id;
};
struct node{
    int val;
}tree[N << 2];
vector<chimer> Q[N];
void push_up(int rt) {
    tree[rt].val = min(tree[rt << 1].val, tree[rt << 1 | 1].val);
}
void build(int l, int r, int rt) {
    if(l == r) {
        tree[rt].val = 0x3f3f3f3f; return;
    }
    int mid = l + r >> 1;
    build(l, mid, rt << 1); build(mid + 1, r, rt << 1 | 1);
    push_up(rt);
}
int query(int a, int b, int l, int r, int rt) {
    if(b < l || a > r) return INF;
    if(l >= a && r <= b) {
        return tree[rt].val;
    }
    int mid = l + r >> 1;
    return min(query(a, b, l, mid, rt << 1), query(a, b, mid + 1, r, rt << 1 | 1));
}
void modify(int pos, int x, int l, int r, int rt) {
    if(l == r) {
        tree[rt].val = x;
        return;
    }
    int mid = l + r >> 1;
    if(pos <= mid) modify(pos, x, l, mid, rt << 1);
    else modify(pos, x, mid + 1, r, rt << 1 | 1);
    push_up(rt);
}
void de(int l, int r, int rt) {
    if(l == r) {
        cout << l << ":" << tree[rt].val << " "; return;
    }
    int mid = l + r >> 1;
    de(l, mid, rt << 1); de(mid + 1, r, rt << 1 | 1);
}
int main() {
    scanf("%d %d", &n, &m);
    for(int i = 1; i <= n; ++ i) scanf("%d", &a[i]), b[i] = a[i];
    for(int i = 1; i <= m; ++ i) { int l, r; scanf("%d %d", &l, & r); Q[r].push_back({l, i});}
    sort(b + 1, b + n + 1); int tot = unique(b + 1, b + n + 1) - b - 1;
    for(int i = 1; i <= n; ++ i) {
        int num = lower_bound(b + 1, b + tot + 1, a[i]) - b;
        pos[i] = pre[num], pre[num] = i;

    }

    build(1, n, 1);
    for(int i = 1; i <= n; ++ i) {
        if(pos[i]) modify(pos[i], i - pos[i], 1, n, 1);

        for(auto j : Q[i]) {
            ans[j.id] = query(j.l, i, 1, n, 1);

        }
    }
    //de(1, n, 1);
    for(int i = 1; i <= m; ++ i) {
        if(ans[i] == INF) ans[i] = -1;
        printf("%d\n", ans[i]);
    }

    return 0;
}
posted @ 2022-03-22 19:54  qingyanng  阅读(21)  评论(0编辑  收藏  举报