ZOJ3574(归并排序求逆数对)

Under Attack II

Time Limit: 5 Seconds      Memory Limit: 65536 KB

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.

题意:一个长方形区域,n条直线切这长方形区域,问被这一个长方形区域被切成多少块?

思路:可推出公式:切成多少块=直线交点数+直线数+1;难点是要去求直线交点数。先开始暴力两个for(O(n^2))直接TLE,这里要用到归并排序求逆数对。

转:http://acshiryu.github.io/2014/12/16/ZOJ3574-Under-Attack-II%E8%A7%A3%E9%A2%98%E6%8A%A5%E5%91%8A/#more

假设,每一条边都已经固定在矩形上,然后,我们从矩形的左边开始看起,从下到上,映射到右边,如果在右边观看时,碰到有k个点(这些点对应的边一定要看过,也就是说对应左边的点要低)在上面,则说明该线段与前面的线段有k个交点。你也许不是很明白,看图,对应左边序号的123456,右边是246135,也就是说对于4号线,有1,3号线的左边低于4,右边高于4,则第4号线与前三条有两个交点,这不正是刚才要求的。现在转换成这样,是不是很熟悉,没错,求逆序对。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<queue>
 4 #include<algorithm>
 5 using namespace std;
 6 struct Node
 7 {
 8   int y1;
 9   int y2;
10 };
11 Node node[30000+100];
12 int t[30000+100];
13 int a[30000+100];
14 int cmp(Node a,Node b)
15 {
16     return a.y1<b.y1;
17 }
18 
19 int cnt;
20 void merge_sort(int x,int y)//归并排序模板
21 {
22     if(y-x>1)
23     {
24         int m=x+(y-x)/2;
25         int p=x,q=m,i=x;
26         merge_sort(x,m);
27         merge_sort(m,y);
28         while(p<m||q<y)
29         {
30             if(q>=y||(p<m&&a[p]<=a[q]))
31                 t[i++]=a[p++];
32             else
33                 {
34                     t[i++]=a[q++];
35                     cnt+=m-p;
36                 }
37         }
38         for(i=x;i<y;i++)
39             a[i]=t[i];
40     }
41 }
42 int main()
43 {
44     int x1,x2;
45     while(~scanf("%d%d",&x1,&x2))
46     {
47         int n;
48         scanf("%d",&n);
49         memset(node,0,sizeof(node));
50         memset(t,0,sizeof(t));
51         int k,b;
52         for(int i=0;i<n;i++)
53         {
54             scanf("%d%d",&k,&b);
55             node[i].y1=k*x1+b;
56             node[i].y2=k*x2+b;
57         }
58         cnt=0;
59         sort(node,node+n,cmp);
60         for(int i=0;i<n;i++)
61             a[i]=node[i].y2;
62         merge_sort(0,n);
63         printf("%d\n",n+cnt+1);
64     }
65 
66     return 0;
67 }
68 
69 //1 2
70 //1
71 //1 5

 

posted @ 2015-07-30 22:52  JoneZP  阅读(389)  评论(0编辑  收藏  举报