题目
题意
给n条线段,要么水平要么垂直,都不相交(除了水平和垂直的)。求能组成的矩形个数。
思路
md思路错了,这题给我整自闭了
暴力枚举复杂度
O
(
n
4
)
O(n^4)
O(n4)。
考虑固定两条水平的,枚举垂直的,假设有
x
x
x条能垂直切割那两条水平的线段,那么这两条水平的对答案的贡献就是
C
(
n
,
2
)
C(n,2)
C(n,2),这样复杂度
O
(
n
3
)
O(n^3)
O(n3)。
继续优化:
考虑枚举一条水平的线段
l
[
i
]
l[i]
l[i],将与它垂直的并且相交的线段的切割点的横坐标加入BIT,从
l
[
i
]
.
x
l[i].x
l[i].x往上扫,考虑矩形的上边与BIT里的线段的交点,并计算贡献。当然向上扫的过程中也要不停的把BIT里的线段删去(当垂直的线段不能再有贡献的时候)。
/* Author : Rshs
* Data : 2019-09-25-19.22
*/
#include<bits/stdc++.h>
using namespace std;
#define FI first
#define SE second
#define LL long long
#define MP make_pair
#define PII pair<int,int>
#define SZ(a) (int)a.size()
const double pai = acos(-1);
const double eps = 1e-10;
const LL mod = 1e9+7;
const int MX = 1e4+20;
/*************************************************************/
LL bit[MX];
void up(int p,LL x,int nn){
while(p<=nn) bit[p]+=x,p=p+(p&-p);
}
LL qu(int p){
LL re=0;
while(p>0) re+=bit[p],p=p-(p&-p);
return re;
}
/*************************************************************/
struct LINE {
int a,b,x,y;
}line[MX];
bool cmp(LINE u,LINE v){
return u.y<v.y;
}
vector<LINE>v,hh;
vector<LINE>h[MX];
vector<int>bj[MX];
int main(){
LL n;cin>>n;
for(int i=1;i<=n;i++){ //1,10001
int sa,sb,sc,sd;cin>>sa>>sb>>sc>>sd;
line[i].a=min(sa,sc)+5001,line[i].x=max(sa,sc)+5001;
line[i].b=min(sb,sd)+5001,line[i].y=max(sb,sd)+5001;
if(line[i].x==line[i].a) v.push_back(line[i]);
else h[line[i].y].push_back(line[i]),hh.push_back(line[i]);
}
LL ans=0;
for(auto i:hh){
memset(bit,0,sizeof(bit));
for(int i=0;i<=1e4+2;i++) bj[i].clear();
int ta=i.a,tx=i.x,ty=i.y;
for(auto j:v){
if(j.x>tx||j.x<ta||j.y<ty||j.b>ty) continue;//无相交
bj[j.y+1].push_back(j.x);//消除的标记
up(j.x,1,1e4+5);
}
for(int j=i.y+1;j<=1e4+1;j++){
for(auto k:bj[j]) up(k,-1,1e4+5);//标记处理
for(auto now:h[j]){
LL gg=qu(now.x)-qu(now.a-1);
ans=ans+gg*(gg-1)/2;
}
}
}
cout<<ans;
return 0;
}