题意

\(n\)\(n\leq 5000\))个平行于x轴或平行于y轴的线段。求这些线段围成了多少个长方形。由多个长方形拼成的也算。

题解

考虑暴力的做法:先分别计算每条横着的线与哪些竖着的线有交点,再枚举两条横着的线,求与它们都有交点的线的个数,在这些线中选两条和这两条横着的线拼成长方形。
发现与同一条竖着的线有交点的横线一定是把所有横线按纵坐标排序后连续的一段。
感谢伟大的YSF!!!

代码

#include<algorithm>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<ctime>
#include<iomanip>
#include<iostream>
#include<map>
#include<queue>
#include<set>
#include<stack>
#include<vector>
#define rep(i,x,y) for(register int i=(x);i<=(y);++i)
#define dwn(i,x,y) for(register int i=(x);i>=(y);--i)
#define view(u,k) for(int k=fir[u];~k;k=nxt[k])
#define LL long long
#define maxn 5007
using namespace std;
int read()
{
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)&&ch!='-')ch=getchar();
    if(ch=='-')f=-1,ch=getchar();
    while(isdigit(ch))x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
    return x*f;
}
void write(LL x)
{
    if(x==0){putchar('0'),putchar('\n');return;}
    int f=0;char ch[20];
    if(x<0)putchar('-'),x=-x;
    while(x)ch[++f]=x%10+'0',x/=10;
    while(f)putchar(ch[f--]);
    putchar('\n');
    return;
}
struct node{int x,l,r;}a[maxn],b[maxn];
int n,tr[maxn+maxn],maxk=5001,sz=10002,cnta,cntb;
LL ans;
vector<int>ed[maxn];
node maken(int x,int l,int r){node tmp;tmp.x=x,tmp.l=l,tmp.r=r;return tmp;}
LL c(int x){return (LL)x*(x-1ll)/2ll;}
int lt(int x){return x&(-x);}
void add(int x,int k){for(;x<=sz;x+=lt(x))tr[x]+=k;return;}
int ask(int x){int k=0;for(;x;x-=lt(x))k+=tr[x];return k;}
int yes(node x,node y)
{
    if(y.l<=x.x&&x.x<=y.r&&x.l<=y.x&&y.x<=x.r)return 1;
    return 0;
}
bool cmpx(node x,node y){return x.x<y.x;}
bool cmpr(int x,int y){return b[x].r<b[y].r;}
int main()
{
    n=read();
    rep(i,1,n)
    {
        int x1=read(),y1=read(),x2=read(),y2=read();
        if(x1>x2)swap(x1,x2);
        if(y1>y2)swap(y1,y2);
        if(y1==y2)a[++cnta]=maken(y1,x1,x2);
        else b[++cntb]=maken(x1,y1,y2);
    }
    sort(a+1,a+cnta+1,cmpx);
    rep(i,1,cnta)
    {
        rep(j,1,cntb)if(yes(a[i],b[j]))
        {
            add(b[j].x+maxk,1);
            ed[i].push_back(j);
        }
        int li=ed[i].size(),now=-1;
        sort(ed[i].begin(),ed[i].end(),cmpr);
        rep(j,i+1,cnta)
        {
            while((now+1)<li&&b[ed[i][now+1]].r<a[j].x)add(b[ed[i][now+1]].x+maxk,-1),now++;
            int num=ask(a[j].r+maxk)-ask(a[j].l+maxk-1);
            ans+=c(num);
        }
        while((now+1)<li)add(b[ed[i][now+1]].x+maxk,-1),now++;
    }
    write(ans);
    return 0;
}
02-11 06:03