题目链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=5862
题意:
2
4
1 0 1 3
2 0 2 3
0 1 3 1
0 2 3 2
4
0 0 2 0
3 0 3 2
3 3 1 3
0 3 0 2
看样例,题意很简单。t个case,每个case第一行n条线段,下面n行每行给出一个线段的端点。这些线段要么与x垂直,要么与y垂直。问能形成多少个交点。不会有重合的线段。
参考博客:http://www.cnblogs.com/fenice/p/5786003.html 感谢!
扫描线这个东西,一直以为是一种算法,现在看来更多的是一种思想吧。
首先将竖直和水平的线段分开来存,把所有的竖直线段按照上端点从大到小排序,再将水平线段按纵坐标y从大到小排序。这样之后我们便可以把水平线段看作一条条直线,从上到下每条直线向下扫,一直扫到不可能再有交点也就是到某个竖直线段的上端点小于水平线段高度,每扫一个点更新树状数组+1。这样扫的同时将每条竖直线段的下端点加入到一个大顶堆里,扫完后再利用优先队列去判断下端点是否满足相交的条件,每不满足一个更新树状数组-1。由于每条线段都要从上往下扫,所以每次开始从上次停止的地方开始扫即可。由于数据量太大,还需要现对x轴上的点进行离散化后再插入到树状数组里。还有几个注意点在注释里标出来了。很巧妙的算法,研究了一天才研究明白。。。太菜了啊。。。大一大二都干嘛去了啊。。。后悔啊。。。区域赛怎么搞啊。。。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
using namespace std;
typedef long long ll;
//下标从1开始 ,开4倍最保险,因为一条线段四个点
const int MAXN = 400100;
int sum[MAXN];
int N;
struct node {
int pos, s, e;
node (int a, int b, int c) : pos(a), s(b), e(c) {}
};
vector<node> x, y;
vector<int> ha;
bool cmpy(node a, node b) {
return a.e > b.e;
}
bool cmpx(node a, node b) {
return a.pos > b.pos;
}
int lowbit(int x) {
return x & (-x);
}
void update(int index, int val) {
int i;
for(i = index; i <= 4 * N; i += lowbit(i)) { //要遍历到最大可能的节点,因为大小不确定
sum[i] += val;
}
}
ll getsum(int index) {
int i;
ll res = 0;
for(i = index; i > 0; i -= lowbit(i)) {
res += sum[i];
}
return res;
}
int main() {
int t;
scanf("%d", &t);
while(t--) {
memset(sum, 0, sizeof(sum));
x.clear();
y.clear();
ha.clear();
scanf("%d", &N);
int x1, y1, x2, y2;
int i;
for(i = 0; i < N; i++) {
scanf("%d %d %d %d", &x1, &y1, &x2, &y2);
if(y1 == y2) { //横
if(x1 > x2) swap(x1, x2);
x.push_back(node(y1, x1, x2));
ha.push_back(x1);
ha.push_back(x2);
}
else {
if(y1 > y2) swap(y1, y2);
y.push_back(node(x1, y1, y2));
ha.push_back(x1);
}
}
sort(ha.begin(),ha.end());
ha.erase(unique(ha.begin(), ha.end()) , ha.end());
sort(y.begin(), y.end(), cmpy);
sort(x.begin(), x.end(), cmpx);
int p = 0;
ll ans = 0; //的确有可能超long long
priority_queue<pair<int, int> > pq;
for(i = 0; i < x.size(); i++) {
while(p < y.size() && x[i].pos <= y[p].e) {
int id = lower_bound(ha.begin(), ha.end(), y[p].pos) - ha.begin() + 1;
update(id, 1);
pq.push(make_pair(y[p].s, id));
p++;
}
while(!pq.empty() && pq.top().first > x[i].pos) {
update(pq.top().second, -1);
pq.pop();
}
int lid = lower_bound(ha.begin(), ha.end(), x[i].s) - ha.begin() + 1;
int rid = lower_bound(ha.begin(), ha.end(), x[i].e) - ha.begin() + 1;
ans += getsum(rid) - getsum(lid - 1);
}
printf("%I64d\n", ans);
}
return 0;
}