逆序对-ZOJ - 3574

Because of the sucessfully calculation in Under Attack I, Doctor is awarded with Courage Cross and promoted to lieutenant. But the war seems to end in never, now Doctor has a new order to help anti-aircraft troops calculate the proper number of supply sites needed for SAMs in battle regions.

According to intel, enemy bombers go straight across battle region and the bombing runs are continous. So their routes divides the region into several parts. The missles SAM needed are provided by supply sites. Because it’s dangerous to cross fireline, Ufo suggests that every part of battle regions divided by firelines should have a supply site so that the SAMs can safely get enough ammo.

Now that the task is clear, Doctor is asked to calculate how many supply sites are at least needed. The bombers’ routes are lines y=kx+b given in format as k,b, of course k b are same to their ordinary meanings. Assume the battle region is a rectangle with infinity height, the left x-cooridinate and right x-cooridinate are given so that the width of rectangle is fixed.

Input
The input consists of multiple cases.
The first line are the left x-cooridinate a and right x-cooridinate b of battle region. a b are both in the range of [0,1000]. Of course a will not exceed b.
Next lines will describe enemy bombing routes number n.n can be up to 30000.
Following n lines are k and b of each bombing route.k b are in range of [-100000,100000].
It’s guaranteed that no three lines (including the two battle region bound lines) will go through one point.

Output
Output the least number of supply sites needed.

Sample Input
1 2
1
1 5
Sample Output
2
Hint
In sample, line y=x+5 divides the region between x=1 and x=2 into two parts, so the outcome is 2.

思路:
若某条直线与左边界的交点高度低于另一条直线而且与右边界的交点高于这一条直线那么这两条直线有交点,
这些直线把整个区域分成的个数为:直线条数+交点个数+1

求交点则会用到逆序对;

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int x1,x2,n,k,b;
const int maxn=60009;
int a[maxn];
int t[maxn];
struct node
{
    int aa,bb;
} e[maxn];

int cmp(node a,node b)
{
    return a.aa<b.aa;
}
int ans=0;
void cal(int l,int r)
{
    if(l+1<r)
    {
        int m=l+(r-l)/2;
        cal(l,m);
        cal(m,r);
        int p=l,q=m;
        int i=l;
        while(p<m||q<r)
        {
            if(q>=r||(p<m&&a[p]<=a[q]))
                t[i++]=a[p++];
            else
            {
                t[i++]=a[q++];
                ans+=m-p;
            }
        }
        for(int i=l;i<r;i++)
            a[i]=t[i];
    }

}
int main()
{
    while(~scanf("%d%d",&x1,&x2))
    {
        scanf("%d",&n);
        for(int i=0; i<n; i++)
        {
            scanf("%d%d",&k,&b);
            e[i].aa=k*x1+b;
            e[i].bb=k*x2+b;
        }

        sort(e,e+n,cmp);
        for(int i=0;i<n;i++)
            a[i]=e[i].bb;

        ans=0;
        cal(0,n);
        printf("%d\n",n+ans+1);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值