hdu 4864(2) 线段树

对task和machine的yi由小到大进行排序,然后对machine来跟task配对。当machine[].yi >= task[].yi时,就更新线段树,在1-1440上做线段树,线段树存的是task[].xi,同时用用优先队列保存task[].yi;当machine[].yi < task[].yi时,就查找 1到machine[].xi最大的值。如果存在最大值的话,把优先队列里的task[].yi取出来。。这样一个machine就匹配到了一个最优的任务。还是看代码好好意会吧,细节挺多的

 1 #include<iostream>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<cstdio>
 5 #include<string>
 6 #include<queue>
 7 #include<cmath>
 8 #include<map>
 9
10 using namespace std;
11
12 #define mnx 100050
13 #define ll long long
14 #define inf 0x3f3f3f3f
15 #define lson l, m, rt << 1
16 #define rson m+1, r, rt << 1 | 1
17
18 priority_queue<int> q[1500];
19 int cnt[1500], sum[8000];
20 struct s{
21     int xi, yi;
22     bool operator < ( const s & b ) const{
23         return yi < b.yi;
24     }
25 }a[mnx], b[mnx];
26 void pushup( int rt ){
27     sum[rt] = max( sum[rt<<1], sum[rt<<1|1] );
28 }
29 void build( int l, int r, int rt ){
30     if( l == r ){
31         sum[rt] = -1;
32         return ;
33     }
34     int m = ( l + r ) >> 1;
35     build( lson ), build( rson );
36     pushup( rt );
37 }
38 int find( int L, int R, int l, int r, int rt ){
39     if( L <= l && R >= r ){
40         return sum[rt];
41     }
42     int m = ( l + r ) >> 1;
43     int ret = -1;
44     if( L <= m ) ret = max( ret, find( L, R, lson ) );
45     if( R > m ) ret = max( ret, find( L, R, rson ) );
46     return ret;
47
48 }
49 void update( int u, int v, int l, int r, int rt ){
50     if( l == r ){
51         sum[rt] = v;
52         return ;
53     }
54     int m = ( l + r ) >> 1;
55     if( u <= m ) update( u, v, lson );
56     else update( u, v, rson );
57     pushup( rt );
58 }
59 int main(){
60     int n, m;
61     const int nn = 1450;
62     while( scanf( "%d%d", &n, &m ) != EOF ){
63         for( int i = 0; i < nn; i++ ){
64             while( !q[i].empty() ) q[i].pop();
65         }
66         memset( cnt, 0, sizeof(cnt) );
67         for( int i = 0; i < n; i++ ){
68             scanf( "%d%d", &a[i].xi, &a[i].yi );
69         }
70         for( int i = 0; i < m; i++ ){
71             scanf( "%d%d", &b[i].xi, &b[i].yi );
72         }
73         sort( a, a+n );
74         sort( b, b+m );
75         build( 1, nn, 1 );
76         int j = 0, ans1 = 0; ll ans2 = 0;
77         for( int i = 0; i < n; i++ ){
78             while( j < m && a[i].yi >= b[j].yi ){
79                 if( !cnt[b[j].xi] ){
80                     update( b[j].xi, b[j].xi, 1, nn, 1 );
81                 }
82                 cnt[b[j].xi]++;
83                 q[b[j].xi].push( b[j].yi );
84                 j++;
85             }
86             int t = find( 1, a[i].xi, 1, nn, 1 );
87             if( t == - 1 ) continue;
88             cnt[t]--;
89             if( cnt[t] == 0 ) update( t, -1, 1, nn, 1 );
90             int tt = q[t].top();  q[t].pop();
91             ans1++;
92             ans2 += t * 500 + tt * 2;
93         }
94         printf( "%d %I64d\n", ans1, ans2 );
95     }
96     return 0;
97 }

hdu 4864(2) 线段树

时间: 2024-07-31 04:34:53

hdu 4864(2) 线段树的相关文章

HDU 1542 Atlantis 线段树+离散化+扫描线

题意:给出一些矩形的最上角坐标和右下角坐标,求这些矩形的面积并. NotOnlySuccess 线段树专辑中扫描线模板题,弱智的我对着大大的代码看了一下午才搞懂. 具体见思路见注释=.= #include <cstdio> #include <cstring> #include <algorithm> #include <vector> #define lson rt<<1,l,mid #define rson rt<<1|1,mid

HDU 1828 Picture 线段树+扫描线

题意:给你一些矩形的左上角点的坐标和右下角点的坐标,求周长并 最显而易见的思路就是对于x轴和y轴做两次扫描线,对于负数的坐标进行离散化.每次增加的值是线段变化量的绝对值.具体写法和求面积并的差不多. #include <cstdio> #include <algorithm> #include <cstring> #include <vector> using namespace std; #define lson rt << 1 , l , m

HDU 1542 Atlantis(线段树扫描线)

http://acm.hdu.edu.cn/showproblem.php?pid=1542 Atlantis Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 6788    Accepted Submission(s): 2970 Problem Description There are several ancient Greek

POJ 1177/HDU 1828 picture 线段树+离散化+扫描线 轮廓周长计算

求n个图矩形放下来,有的重合有些重合一部分有些没重合,求最后总的不规则图型的轮廓长度. 我的做法是对x进行一遍扫描线,再对y做一遍同样的扫描线,相加即可.因为最后的轮廓必定是由不重合的线段长度组成的,这样理论上是对的 要注意处理高度相同的线段,把底边优先处理(在代码里就是f标记为1的线段),因为若是一个矩形的底边和另一个矩形的上边重合,则这个轮廓肯定不能算 不过POJ和HDU的数据好像都比较弱,我没进行上面的细节处理也AC了,不过一个很简单的数据就会不对,所以还是要处理一下才是真正正确的代码 我

hdu 1542 Atlantis(线段树&amp;扫描线&amp;面积并)

Atlantis Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 6386    Accepted Submission(s): 2814 Problem Description There are several ancient Greek texts that contain descriptions of the fabled i

hdu 1828 Picture(线段树&amp;扫描线&amp;周长并)

Picture Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2578    Accepted Submission(s): 1363 Problem Description A number of rectangular posters, photographs and other pictures of the same shap

hdu 1542 Atlantis(线段树)

Atlantis Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 6899    Accepted Submission(s): 3022 Problem Description There are several ancient Greek texts that contain descriptions of the fabled i

HDU 1166(线段树单点更新)

HDU 1166 题意:1-n个堡垒,人数在不断变化,多次查询 l-r人数和: 思路:线段树的单点更新: #include<iostream> #include<cstring> #include<cstdio> #include<string> #include<algorithm> #include<cmath> #include<map> #include<vector> #include<queu

HDU 3308 LCIS (线段树区间合并)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3308 题目很好懂,就是单点更新,然后求区间的最长上升子序列. 线段树区间合并问题,注意合并的条件是a[mid + 1] > a[mid],写的细心点就好了. 1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 using namespace std; 5 const int MAXN = 1