CF1194E Count The Rectangles(树状数组)

对于这种题目,基本上都是先枚举后维护信息。

自然的想到从小到大枚举横边或竖边,之后维护另一种边。

因为要区间计数,所以考虑树状数组,只要满足边穿过枚举边的都可以加入。

在固定最低边后往后枚举,计算组合数,并且注意删除不满足题意的边

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pll;
const int N=2e5+10;
const int inf=0x3f3f3f3f;
int tr[N];
int lowbit(int x){
    return x&-x;
}
void add(int x,int c){
    int i;
    for(i=x;i<N;i+=lowbit(i)){
        tr[i]+=c;
    }
}
ll sum(int x){
    ll ans=0;
    for(int i=x;i;i-=lowbit(i)){
        ans+=tr[i];
    }
    return ans;
}
vector<pll> row[N];
vector<pll> col[N];
vector<int> num[N];
int main(){
    ios::sync_with_stdio(false);
    int n;
    cin>>n;
    int i;
    for(i=1;i<=n;i++){
        int x1,y1,x,y;
        cin>>x>>y>>x1>>y1;
        x+=5001;
        y+=5001;
        x1+=5001;
        y1+=5001;
        if(y==y1){
            if(x>x1)
                swap(x,x1);
            row[y].push_back({x,x1});
        }
        else{
            if(y>y1)
            swap(y,y1);
            col[x].push_back({y,y1});
        }
    }
    ll ans=0;
    for(int i=1;i<10004;i++){
        for(auto x:row[i]){
            for(int j=0;j<10004;j++)
                num[j].clear();
            for(int j=x.first;j<=x.second;j++){
                for(auto y:col[j]){
                    if(y.first<=i&&y.second>i){
                        num[y.second].push_back(j);
                        add(j,1);
                    }
                }
            }
            for(int j=i+1;j<10004;j++){
                for(auto y:row[j]){
                    ll res=sum(y.second)-sum(y.first-1);
                    ans+=res*(res-1)/2;
                }
                for(auto y:num[j])
                    add(y,-1);
            }
        }
    }
    cout<<ans<<endl;
}
View Code

 

posted @ 2020-10-15 23:18  朝暮不思  阅读(114)  评论(0编辑  收藏  举报