[未完]2016多校10 HDU 5862 Counting Intersections

11 篇文章 0 订阅
6 篇文章 0 订阅

2016多校联合训练#10

HDU 5862 Counting Intersections

线段树,扫描线


题意

给一些平行与坐标轴的线段,求交点个数。线段之间没有公共端点,没有重叠,没有长度0的。


思路

扫描线。。线段树维护。。我是不会树状数组。。。

保存竖线,保存横线的端点,记录左右。遇到左端点右端点更新线段树,遇到竖线查询。

但是我为什么tmd过不去。。。。


代码

WA的代码!!!以后再改吧

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <vector>
#include <queue>
#include <stack>
#include <iomanip>
#include <string>
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1

using namespace std;
const int MAXN=100005;
const int oo=1000000007;
typedef long long int LL;
struct Tree{
    int sum;
}tree[MAXN<<2];
struct Linev{
    int d,u;
    int x;
    int sign;
    bool operator < (const Linev &l)const
    {
        return x<l.x;
    }
}v[MAXN<<1];
int h[MAXN<<1];

void PushUP(int rt)
{

    tree[rt].sum=tree[rt<<1].sum+tree[rt<<1|1].sum;
}

void build(int l,int r,int rt)
{
    if(l==r)
    {
        tree[rt].sum=0;
        return;
    }
    int m=(l+r)>>1;
    build(lson);
    build(rson);
    PushUP(rt);
}

void update(int x,int p,int l,int r,int rt)
{
    if(l==r)
    {
        tree[rt].sum+=p;
        return;
    }
    int m=(l+r)>>1;
    if(x<=m) update(x,p,lson);
    if(x>m) update(x,p,rson);
    PushUP(rt);
}

LL query(int L,int R,int l,int r,int rt)
{
    if(L<=l&&r<=R)
    {
        return (LL)tree[rt].sum;
    }
    int m=(r+l)>>1;
    LL res=0;
    if(L<=m) res+=(LL)query(L,R,lson);
    if(m<R) res+=(LL)query(L,R,rson);
    return res;
}

int main()
{
    freopen("1006.in","r",stdin);
    freopen("out.out","w",stdout);
    int T;
    scanf("%d",&T);
    while(T--)
    {
        memset(v,0x3f,sizeof(v));
        memset(h,0x3f,sizeof(h));
        int n;
        scanf("%d",&n);
        int cnth=0;
        int cntv=0;
        for(int i=0;i<n;i++)
        {
            int a,b,c,d;
            scanf("%d%d%d%d",&a,&b,&c,&d);
            if(a==c)
            {
                if(b<d) swap(b,d);
                v[cntv].d=d;v[cntv].u=b;v[cntv].x=a;v[cntv++].sign=0;
                h[cnth++]=b;h[cnth++]=d;
            }
            else if(b==d)
            {
                if(a>c) swap(a,c);
                v[cntv].d=b;v[cntv].u=b;v[cntv].x=a;v[cntv++].sign=1;
                v[cntv].d=b;v[cntv].u=b;v[cntv].x=c;v[cntv++].sign=-1;
                h[cnth++]=b;
            }
        }
        sort(v,v+cntv);
        sort(h,h+cnth);
        int m=1;
        for(int i=1;i<cnth;i++)
        {
            if(h[i]!=h[i-1])
            {
                h[m++]=h[i];
            }
        }

        build(1,m,1);
        LL res=0;
        for(int i=0;i<cntv;i++)
        {
            if(v[i].sign==1)
            {
                int y=lower_bound(h,h+m,v[i].d)-h+1;
                update(y,1,1,m,1);
            }
            else if(v[i].sign==-1)
            {
                int y=lower_bound(h,h+m,v[i].d)-h+1;
                update(y,-1,1,m,1);
            }
            else
            {
                int l=lower_bound(h,h+m,v[i].d)-h+1;
                int r=lower_bound(h,h+m,v[i].u)-h+1;
                if(l<=r) res+=(LL)query(l,r,1,m,1);
            }
        }
        printf("%lld\n",res);

    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值