Good Inflation SPOJ

题目传送门

题意:刚开始有一个气球体积为空,现在有n个充气点,从1->n遍历这n充气点,每个充气点有vi,di,vi为走到这个充气点之后可以为气球充气vi的体积,di为选择了在这个点充气的时候,每次往后走气球会漏di的气体。

题解:李超线段树裸题。

李超树主要是维护优势线段。

每一个节点存一条线段的信息。

每次更新的时候,如果新的线段完全在原来的下方,直接return,

如果新的线段在原来的直线的上方,这存下新的线段。

否者就是有交点,我们继续往下走,更新一下下面的线段。

注意的就是,每个节点只存一条线段的内容, 有2条线段出现在[l,r]这个节点中的时候,我们存下优势长的那一条信息。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout);
 4 #define LL long long
 5 #define ULL unsigned LL
 6 #define fi first
 7 #define se second
 8 #define pb push_back
 9 #define lson l,m,rt<<1
10 #define rson m+1,r,rt<<1|1
11 #define lch(x) tr[x].son[0]
12 #define rch(x) tr[x].son[1]
13 #define max3(a,b,c) max(a,max(b,c))
14 #define min3(a,b,c) min(a,min(b,c))
15 typedef pair<int,int> pll;
16 const int inf = 0x3f3f3f3f;
17 const LL INF = 0x3f3f3f3f3f3f3f3f;
18 const LL mod =  (int)1e9+7;
19 const int N = 1e6 + 100;
20 LL treeb[N<<2],treek[N<<2];
21 bool vis[N<<2];
22 double Intersection(double k1,double b1,double k2,double b2){return 1.0*(b2-b1)/(k1-k2);}
23 void update(LL k,LL b,int l,int r,int rt){
24     if(!vis[rt]) {
25         treek[rt] = k;
26         treeb[rt] = b;
27         vis[rt] = 1;
28         return;
29     }
30     LL l1 = k * l + b, l2 = treek[rt] * l + treeb[rt];
31     LL r1 = k * r + b, r2 = treek[rt] * r + treeb[rt];
32     if(l1 <= l2 && r1 <= r2) return ;
33     if(l1 >= l2 && r1 >= r2) treek[rt] = k, treeb[rt] = b;
34     else{
35         int m = l + r >> 1;
36         double crs = Intersection(k, b, treek[rt], treeb[rt]);
37         if(l1 >= l2){
38             if(crs <= m) update(k,b,lson);
39             else{
40                 update(treek[rt], treeb[rt], rson);
41                 treek[rt] = k; treeb[rt] = b;
42             }
43         }
44         else{
45             if(crs > m) update(k, b, rson);
46             else{
47                 update(treek[rt], treeb[rt], lson);
48                 treek[rt] = k; treeb[rt] = b;
49             }
50         }
51     }
52 }
53 
54 
55 
56 
57 LL query(int x,int l,int r,int rt){
58     LL ans=0;
59     if(vis[rt]) ans=max(ans, x*treek[rt]+treeb[rt]);
60     if(l == r) return ans;
61     int m = l+r >> 1;
62     if(m >= x) ans = max(ans, query(x, lson));
63     else ans = max(ans, query(x, rson));
64     return ans;
65 }
66 int v[N], d[N];
67 int main(){
68     int n;
69     scanf("%d", &n);
70     for(int i = 1; i <= n; i++)
71         scanf("%d%d", &v[i], &d[i]);
72     update(-d[1],v[1]+d[1],0,n+1,1);
73     for(int i = 2; i <= n; i++){
74         LL zz = query(i,0,n+1,1) + v[i];
75         update(-d[i],zz+1ll*d[i]*i,0,n+1,1);
76     }
77     LL ans = query(n+1,1,n,1);
78     if(ans < 0) ans = 0;
79     cout << ans << endl;
80     return 0;
81 }
View Code
原文地址:https://www.cnblogs.com/MingSD/p/9856091.html