P5677 [GZOI2017] 配对统计

原题链接

题解 ,太不容易了

  1. \(a_i!=a_j\) 所以对于每一个数而言,最多有两个配对,最少有一个配对。即排序之后,前后哪个离自己更近就和谁配对
  2. \((x,y)!=(y,x)\)
  3. 把配对看成区间
  4. \(tree[i]\) 代表有多少个区间的左端点大于 \(i\)
  5. 把查询按右端点排序,顺序遍历 \(i\),把右端点小于 \(i\) 的区间存起来(树状数组),这样我就保证了 \(tree[r]-tree[l-1]\) 是符合的区间个数(需要把区间也按右端点排序)

code

#include<bits/stdc++.h>
#include<iostream>
using namespace std;
#define lowbit(x) ((x)&(-x))
#define ll long long

void read(ll &x) {
    cin >> x;
}

void write(ll x) {
    cout << x;
}

struct node
{
    ll v, id;
}a[300005];

struct cx
{
    ll l,r,id;
}q[300005];

struct unit
{
    int l,r;
}qj[600006];//把配对看成区间
int cnt=0;//
int tree[300006]={0};//tree[i]代表有多少个区间左端点大于i

bool cmp1(node b, node c) {
    return b.v < c.v;
}

bool cmp3(cx b,cx c)
{
    return b.r<c.r;
}

bool cmp2(unit b,unit c)
{
    return b.r<c.r;
}
ll n, m;
void update(ll x)
{
    while(x<=n)
    {
        tree[x]++;
        x+=lowbit(x);
    }
}

ll query(ll x)
{
    ll sum=0;
    while(x)
    {
        sum+=tree[x];
        x-=lowbit(x);
    }
    return sum;
}

void add(ll x)//代表以a[x].v为x,a[x+1].v为y的配对
{
    qj[++cnt].l=min(a[x].id,a[x+1].id);
    qj[cnt].r=max(a[x].id,a[x+1].id);
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    read(n);
    read(m);

    for(ll i = 1; i <= n; i++)
    {
        read(a[i].v);
        a[i].id = i;
    }

    sort(a+1, a+1+n, cmp1);

    if(n>1)//起码得有区间
    {
        add(1LL);
        add(n-1LL);
    }

    for(ll i = 2; i < n; i++)
    {
        if(a[i].v - a[i-1].v == a[i+1].v - a[i].v)
        {
            add(i-1);
            add(i);
        }
        else if(a[i].v - a[i-1].v < a[i+1].v - a[i].v) add(i-1LL);
        else add(i);
    }
    sort(qj+1,qj+1+cnt,cmp2);

    for(ll i=1;i<=m;i++)
    {
        cin >> q[i].l >> q[i].r;
        q[i].id=i;
    }
    sort(q+1,q+1+m,cmp3);

    ll ans=0;
    ll it=1;
    for(ll i=1;i<=m;i++)
    {
        while(it<=cnt&&qj[it].r<=q[i].r)//只更新右端点小于r的区间,这样一来减一减就有意义了
        {
            update(qj[it].l);
            it++;
        }
        ans+=q[i].id*(query(q[i].r)-query(q[i].l-1LL));
    }

    write(ans);
    return 0;
}

posted @ 2024-04-17 15:42  纯粹的  阅读(65)  评论(0)    收藏  举报