扫描线+树状数组——cf1191F

把所有点离散化,虚构一根扫描线从上往下扫,每行的点从左往右算贡献,开一个树状数组维护每个离散化后的x坐标是否已经有点

扫描到一个点时,先把这个点更新到树状数组里,每个点的贡献是它左边的所有点数*到它相邻右边点之间的所有点数

#include<bits/stdc++.h>
#include<vector>
using namespace std;
#define maxn 200005
struct Node {int x,y;}p[maxn];
int cmp(Node a,Node b){
    if(a.y==b.y)return a.x<b.x;
    return a.y>b.y;
}
int n,m;
vector<int>x,y;

int bit[maxn],f[maxn];
void update(int x){
    while(x<=m){
        bit[x]++;
        x+=x&-x;
    }
}
int query(int x){
    int res=0;
    while(x){
        res+=bit[x];
        x-=x&-x;
    }
    return res;
}

int main(){
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>p[i].x>>p[i].y;
        x.push_back(p[i].x);
    }
    sort(p+1,p+1+n,cmp);
    sort(x.begin(),x.end());
    x.erase(unique(x.begin(),x.end()),x.end());
    m=x.size();
    
    long long ans=0;
    for(int i=1;i<=n;i++){
        int pos,R;
        if(i==n || p[i+1].y!=p[i].y)
            R=m;
            
        else R=lower_bound(x.begin(),x.end(),p[i+1].x)-x.begin()+1-1;
        pos=lower_bound(x.begin(),x.end(),p[i].x)-x.begin()+1;//p[i]所在位置
        if(!f[pos])
            update(pos),f[pos]=1;
        ans+=(long long)query(pos)*(query(R)-query(pos-1));    
    }
    cout<<ans<<endl;
}
原文地址:https://www.cnblogs.com/zsben991126/p/11184503.html