【数据结构】cf91E. Igloo Skyscraper

http://codeforces.com/problemset/problem/91/E

    很简单的题意,给出n条直线编号分别为1~n,再给去m个询问,要求出第L条~第R条直线,在x=xi时最高的是那一条。

    作为一个弱菜我只想到了,O(n*n½ log(n½))的暴力方法,=。=,就是分块sqrt(n)个区域,将询问离线按x坐标递增,每个块内用堆维护求出当前x坐标下最高的直线编号。后来问了我队友,他告诉我用线段树可以处理,相当于线段树每个节点(li,ri),上维护一个下凸曲线,每个节点的曲线可以由其两个子结点线性合并出来,故每层复杂度是O(n) ,总复杂度O(n log(n) )。

   今天太不在状态了,这两个100行左右的程序,墨迹了一个下午,第二个版本还没AC成功,=。=~。自己怎么对拍都没问题,于是决定不管之了

线段树版本
 1 //By Lin
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<vector>
 5 #define maxn 100005
 6 #define inf 0x7fffffff
 7 using namespace std;
 8 typedef long long LL;
 9 
10 int        n,m;
11 struct    Line{
12     int a,b;
13     int    id;
14     void init(int i){ scanf("%d%d", &a, &b ); id = i; }
15     bool operator<(Line c){
16         return (a!=c.a)?(a<c.a):(b<c.b);
17     }
18 }data[maxn];
19 bool    cmp(Line a , Line b ,int t){
20     return a.a+((LL)a.b*t) < b.a+((LL)b.b*t);
21 }
22 int        overtake(Line a, Line b){
23     int t = (b.a-a.a)/(a.b-b.b);
24     if ( cmp(a,b,t) ) t++;
25     return t;
26 }
27 struct    Segtree{
28     int    left[maxn*4],right[maxn*4];
29     int    num[maxn*4];
30     vector<Line> g[maxn*4];
31     vector<int>  h[maxn*4];
32     void meger(int step){
33         int l = step*2 , r = step*2+1,i = 0 , j = 0;
34         while ( i != num[l] || j != num[r] ){
35             if ( i == num[l] ) g[step].push_back( g[r][j++] );
36             else if ( j == num[r] ) g[step].push_back( g[l][i++] );
37             else 
38                 if ( g[l][i].b < g[r][j].b || g[l][i].b==g[r][j].b&&g[l][i].a>g[r][j].a )
39                     g[step].push_back( g[l][i++] );
40                 else
41                     g[step].push_back( g[r][j++] );
42         }
43         int cnt = num[l]+num[r]; 
44         while ( h[step].size()<num[l]+num[r] )  h[step].push_back(0);
45         h[step][0] = -inf; num[step] = 1; 
46         for (int i = 1; i<cnt; i++){
47             if ( g[step][i].b == g[step][num[step]-1].b ) continue;
48             int t = overtake( g[step][i] , g[step][num[step]-1] );
49             while ( t <= h[step][num[step]-1] ) {
50                 num[step]--;
51                 t = overtake( g[step][i] , g[step][num[step]-1] );
52             }
53             g[step][num[step]++] = g[step][i];
54             h[step][num[step]-1] = overtake( g[step][num[step]-1] , g[step][num[step]-2] );
55         }
56     }
57     void build(int l,int r,int step){
58         left[step] = l , right[step] = r;
59         g[step].clear() , h[step].clear();
60         if ( l == r ){
61             g[step].push_back( data[l] ); 
62             h[step].push_back(-inf); 
63             num[step] = 1;
64             return;
65         }
66         int mid = (left[step]+right[step])>>1;
67         build( l , mid , step*2 );
68         build(mid+1 ,r , step*2+1 );
69         meger(step);
70     }
71     pair<LL,int> ask(int l,int r,int t,int step){
72         if ( left[step] == l && right[step] == r ) {
73             int p = 0 , q = num[step]-1,k = 0;
74             while ( p<=q ){
75                 int mid = (p+q)>>1;
76                 if ( h[step][mid] <= t ) k = mid , p = mid+1;
77                 else q = mid-1;
78             }
79             return make_pair( g[step][k].a+((LL)g[step][k].b)*t , g[step][k].id ); 
80         }
81         int mid = ( left[step]+right[step] )>>1;
82         if ( r<=mid ) return ask(l,r,t,step*2);
83         else if ( mid<l ) return ask(l,r,t,step*2+1);
84         else return max( ask(l,mid,t,step*2) , ask(mid+1,r,t,step*2+1) );
85     }
86 }tree;
87 int        main(){
88     scanf("%d%d",&n, &m );
89     for (int i = 1; i<=n; i++) data[i].init(i);
90     tree.build(1,n,1);
91     while ( m -- ){
92         int l, r,t;
93         scanf("%d%d%d", &l , &r, &t );
94         printf("%d\n" , tree.ask(l,r,t,1).second );
95     }
96     return 0;
97 }
分块版本
 1 //By Lin
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<queue>
 5 #include<algorithm>
 6 #define inf  0x7fffffff
 7 #define maxn 100050
 8 #define sqr(x) ((x)*(x))
 9 using namespace std;
10 typedef long long LL;
11 
12 int        n,m;
13 struct    Ask{
14     int l,r,t,num;
15     void init(int i) { scanf("%d%d%d", &l , &r, &t ); l--,r--; num = i; }
16 }asks[maxn];
17 int        ans[maxn];
18 bool    cmp1( const Ask &a , const Ask &b) { return a.t < b.t; }
19 
20 struct    Line{
21     int a,b;
22 }data[maxn];
23 inline LL    compute( Line a, int t ){
24     return a.a+((LL)a.b)*t;
25 }
26 inline int    overtake( Line a, Line b){
27     if ( a.b == b.b && a.a > b.a ) return -inf;
28     if ( a.b <= b.b ) return inf;
29     int t = (b.a-a.a)/(a.b-b.b);
30     if ( compute(a,t) < compute(b,t) ) t++;
31     return t;
32 
33 }
34 int        kcnt,len;
35 struct    Node{
36     int t,w,to;
37     Node(int _t ,int _w , int _to):t(_t),w(_w),to(_to){}
38     bool friend operator<( const Node&a , const Node&b){
39         return a.t > b.t;
40     }
41 };
42 priority_queue<Node> stack[400];
43 int    mx[400];
44 bool    check(LL &x, LL y){
45     if (  x < y ) { x = y;  return true; }
46     return false;
47 }
48 int        main(){
49     scanf("%d%d", &n, &m );
50     for (int i = 0; i<n; i++) scanf("%d%d", &data[i].a , &data[i].b );
51     for (len = 0; sqr(len+1)<=n; len++);
52     kcnt = n/len+(n%len==0?0:1);
53     for (int k = 0; k<kcnt; k++){
54         int st = k*len , ed = min(n,(k+1)*len);
55         mx[k] = st;
56         for (int i = st; i<ed; i++)
57             if ( data[i].b<data[mx[k]].b ) mx[k] = i;
58 //        if ( k == 3 ) printf("%d %d\n" , data[mx[k]].a , data[mx[k]].b );
59         for (int i = st; i<ed; i++) if ( i != mx[k] ) {
60             stack[k].push( Node(overtake(data[i],data[mx[k]]),i,mx[k]) );
61 //            if ( k == 3 ) printf("%d,%d_%d %d %d\n",data[i].a,data[i].b, overtake(data[i],data[mx[k]]),i,mx[k] );
62         }
63     }
64     for (int i = 0; i<m; i++) asks[i].init(i);
65     sort( asks, asks+m, cmp1 );
66 //    printf("%d\n" , len );
67     for (int o = 0; o<m; o++){
68         int l = asks[o].l , r = asks[o].r,
69             st = l/len+1 , ed = r/len, t = asks[o].t;
70         if ( asks[o].num == 31120 ) printf("%d %d %d %d %d\n" , l , r , st , ed , t );
71         LL    key =  -(1ll<<60) , id = 0;
72         if ( st > ed ) {
73             for (int i = l; i<=r; i++) if ( check(key,compute(data[i],t)) ) id = i;
74         }else{
75             for (int i = l; i<st*len; i++) if ( check(key,compute(data[i],t)) ) id =i; 
76             for (int i = ed*len; i<=r; i++)if ( check(key,compute(data[i],t)) ) id =i; 
77             for (int k = st; k<ed; k++){
78                 while ( !stack[k].empty() && stack[k].top().t <= t ){
79                     int w = stack[k].top().w , to = stack[k].top().to; 
80                     stack[k].pop();
81 //                    if ( k == 3 ) printf("!%d %d %d\n" , w, to , t );
82                     if ( to == mx[k] ) mx[k] = w;
83                     else {
84                         stack[k].push( Node(overtake(data[w],data[mx[k]]),w,mx[k]) );
85 //                        printf("now %d %d %d\n" , overtake(data[w],data[mx[k]]),w,mx[k]);
86                     }
87                 }
88 //                printf("%d %d\n" , k , mx[k] );
89                 if ( check(key,compute(data[mx[k]],t)) ) id = mx[k];
90             }
91         }
92         ans[asks[o].num] = id;
93     }
94     for (int i = 0; i<m; i++) printf("%d\n" , ans[i]+1 );
95     return 0;
96 }

 

转载于:https://www.cnblogs.com/lzqxh/archive/2012/12/13/2816684.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值