您的位置:首页 > 其它

POJ 1436 - Horizontally Visible Segments

2012-07-31 10:57 225 查看
题目地址 : http://poj.org/problem?id=1436

题目其实有点搓。 区间查询与更新。

重点在于如何判断。

题意读了好几天,没读懂。。。 还来还是查了别人的翻译,才顿悟了。

水平可见的意思:两垂线段之间,有其中一部分可以相连(即中间没有其它线段)。

所以样例的三元组是:0~3 ,3~4,0~4 。

水平可见部分,分别是:3~3,2~3,3~4。

OK,题意理解后,非常好敲~~

处理一下,将输入的坐标乘以2~~ (点是偶数,边是奇数)~

于是点和边就可以一起放入线段树进行统计了~~

利用Vector(rec数组)记录可见边,利用哈希(has数组)判重。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
#define ll (v<<1)
#define rr (v<<1|1)
#define tmid ((l+r)>>1)

using namespace std;

const int maxn=(8000<<1);

int tree[maxn*4+2];
int lft[maxn+2],rit[maxn+2];
bool has[maxn+2];

struct Line{
int x,y1,y2;
}p[maxn];

vector<int>rec[maxn+2];

void tadd(int ID,int L,int R,int l,int r,int v){
if(L<=l && r<=R && tree[v]!=-2){
if(tree[v]!=-1)
if(has[tree[v]]==false){
has[tree[v]]=true;
rec[ID].push_back(tree[v]);
}
tree[v]=ID;
return;
}
if(tree[v]!=-2){
tree[ll]=tree[rr]=tree[v];
tree[v]=-2;
}
if(L<=tmid)
tadd(ID,L,R,l,tmid,ll);
if(R>tmid)
tadd(ID,L,R,tmid+1,r,rr);
if(L<=l && r<=R)
tree[v]=ID;
}

int cmp(Line a, Line b){
return a.x<b.x;
}

int main(){
int t,n,i,j,k,sum,jn,kn;
scanf("%d",&t);
memset(has,false,sizeof(has));
while(t--){
memset(tree,-1,sizeof(tree));
scanf("%d",&n);
for(i=0;i<n;i++){
scanf("%d%d%d",&p[i].y1,&p[i].y2,&p[i].x);
p[i].y1<<=1;
p[i].y2<<=1;
rec[i].clear();
}
sort(p,p+n,cmp);
sum=0;
for(i=0;i<n;i++){
tadd(i,p[i].y1,p[i].y2,1,maxn,1);
for(j=0,jn=rec[i].size();j<jn;j++)
for(k=0,kn=rec[rec[i][j]].size();k<kn;k++)
if(has[rec[rec[i][j]][k]])
sum++;
for(j=0,jn=rec[i].size();j<jn;j++)
has[rec[i][j]]=false;
}
printf("%d\n",sum);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: