bzoj2149拆迁队 斜率优化dp+分治

2149: 拆迁队

Time Limit: 10 Sec  Memory Limit: 259 MB
Submit: 397  Solved: 177
[Submit][Status][Discuss]

Description

lanxisi带领着他的拆迁队来整治一个街道。这个街道由N个旧房子组成,从左到右编号为1..N。每个旧房子i有一个正整数的美观度Ai

lanxisi希望整个街道从左到右美观度严格递增,也就是保证Ai<Aji<j)。但是旧的街道明显不符合这个要求,于是lanxisi希望拆迁一些旧房子并在原地建立新房子来满足这一要求。但是与很多拆迁队一样,很多钉子户拒绝拆迁。所以lanxisi希望能保留最多的旧房子来满足某些钉子户,当然,保留一个旧房子需要给房子主人Bi的赔偿金。最后,总花费=整治好以后所有房子美观度之和+赔偿金之和。新的美观值也都必须是正整数。

现在,请你求出lanxisi最多能保留多少旧房子和整治这个街道所需要的最少总花费(当然是在保留旧房子最多这个前提下的)。

Input

第一行有1个整数N,表示旧房子个数。第二行有N个整数,第i个数Ai表示旧房子的美观度。第三行有N个整数,第i个数Bi表示保留旧房子的赔偿金。

Output

第一行输出2个整数,表示保留的旧房子数量、总花费的大小。【样例输入一】 4 2 1 7 4 1 5 4 3 【样例输入二】 6 1 6 3 4 7 7 1 2 1 1 1 9

Sample Input

【样例输出一】
2 25

【样例输出二】
4 29

【数据范围】
100%的数据中,1<=N<=100000,0<=Ai,Bi<=100000000。

Sample Output

HINT

Source

这道题2个问 第一问是减去下标求lis 第二问在第一问基础上维护转移

还是有点麻烦 不多哔哔了

这篇博客写得不错http://www.cnblogs.com/zj75211/p/8125193.html

贴个代码

 1 #include<cstdio>
 2 #include<algorithm>
 3 #define N 100005
 4 using namespace std;
 5 typedef long long ll;
 6 int n,m,i,j,k,a[N],b[N],d[N],e[N],bit[N],f[N],ans0,G[N],nxt[N];
 7 int cl,cr,L[N],R[N],top,q[N];
 8 ll c[N],g[N],ans1=1LL<<62;
 9 struct E{int x,t;E(){}E(int _x,int _t){x=_x,t=_t;}}h[N];
10 void read(int&a){char c;while(!(((c=getchar())>=‘0‘)&&(c<=‘9‘)));a=c-‘0‘;while(((c=getchar())>=‘0‘)&&(c<=‘9‘))(a*=10)+=c-‘0‘;}
11 void umax(int&a,int b){if(a<b)a=b;}
12 void umin(ll&a,ll b){if(a>b)a=b;}
13 int lower(int x){
14   int l=1,r=n+1,mid,t;
15   while(l<=r)if(e[mid=(l+r)>>1]<=x)l=(t=mid)+1;else r=mid-1;
16   return t;
17 }
18 void ins(int x,int y){for(;x<=n+1;x+=x&-x)umax(bit[x],y);}
19 int ask(int x){int t=-N;for(;x;x-=x&-x)umax(t,bit[x]);return t;}
20 void add(int x,int y){nxt[y]=G[x];G[x]=y;}
21 bool cmp(int x,int y){return d[x]==d[y]?c[x]>c[y]:d[x]<d[y];}
22 double pos(int x,int y){return 1.0*(c[y]-c[x])/(d[x]-d[y]);}
23 void insert(int x){
24   if(top&&d[x]==d[q[top]])top--;
25   while(top>1&&pos(q[top],x)>pos(q[top],q[top-1]))top--;
26   q[++top]=x;
27 }
28 void query(int x){
29   if(!top)return;
30   int l=1,r=top-1,mid,t=top;
31   while(l<=r){
32     mid=(l+r)>>1;
33     if(x>pos(q[mid],q[mid+1]))r=(t=mid)-1;else l=mid+1;
34   }
35   umin(g[x],1LL*x*d[q[t]]+c[q[t]]);
36 }
37 void solve(int l,int r){
38   if(l==r)return;
39   int mid=(l+r)>>1,i,j;
40   solve(l,mid),solve(mid+1,r);
41   for(cl=0,i=l;i<=mid;i++)if(!h[i].t)L[++cl]=h[i].x;
42   for(cr=0,i=r;i>mid;i--)if(h[i].t)R[++cr]=h[i].x;
43   if(!cl||!cr)return;
44   sort(L+1,L+cl+1,cmp),sort(R+1,R+cr+1,cmp);
45   for(i=j=1,top=0;i<=cr;i++){
46     while(j<=cl&&d[L[j]]<=d[R[i]])insert(L[j++]);
47     query(R[i]);
48   }
49 }
50 int main(){
51   read(n);
52   for(i=1;i<=n;i++)read(a[i]);
53   for(i=1;i<=n;i++)read(b[i]),e[i+1]=d[i]=a[i]-i;
54   sort(e+1,e+n+2);
55   for(i=1;i<=n+1;i++)bit[i]=-N;
56   ins(lower(0),0);
57   for(i=1;i<=n;i++)g[i]=ans1,j=lower(d[i]),ins(j,f[i]=ask(j)+1);
58   ans0=ask(n+1);
59   for(i=0;i<=n;i++)G[i]=-1;
60   for(i=n;~i;i--)if(f[i]>=0)add(f[i],i);
61   for(i=0;i<ans0;i++){
62     j=G[i],k=G[i+1],m=0;
63     while(~j||~k){
64       if(j<0)h[++m]=E(k,1),k=nxt[k];
65       else if(k<0||j<k)h[++m]=E(j,0),j=nxt[j];
66       else h[++m]=E(k,1),k=nxt[k];
67     }
68     solve(1,m);
69     for(k=G[i+1];~k;k=nxt[k]){
70       g[k]+=b[k]+a[k]+1LL*k*(k-1)/2;
71       c[k]=g[k]+1LL*k*(k+1)/2-1LL*a[k]*k-a[k];
72     }
73   }
74   for(i=0;i<=n;i++)if(f[i]==ans0)umin(ans1,g[i]+1LL*(n-i)*a[i]+1LL*(n-i)*(n-i+1)/2);
75     printf("%d %lld",ans0,ans1);
76   return 0;
77 }

原文地址:https://www.cnblogs.com/wsy01/p/8133823.html

时间: 2024-11-09 05:06:01

bzoj2149拆迁队 斜率优化dp+分治的相关文章

【BZOJ1911】[Apio2010]特别行动队 斜率优化DP

想了好久啊.... 用了我感觉比较好写的一种(因为没写过维护凸包),另一种是维护凸包的做法,本质一样?推荐http://www.mamicode.com/info-detail-345781.html. 网上的大多数解法: DP:f[i]=max(f[j]+a*(sum[i]-sum[j])^2+b(sum[i]-sum[j])+c) 显然复杂度不对. 那么假设j>k且f[j]优于f[k] f[j]-f[k]+a*(sum[j]^2-sum[k]^2)-b*(sum[j]-sum[k])>2*

APIO2010 特别行动队 &amp; 斜率优化DP入门讲解

做完此题之后 自己应该算是真正理解了斜率优化DP 根据状态转移方程f[i]=max(f[j]+ax^2+bx+c),x=sum[i]-sum[j] 可以变形为 f[i]=max((a*sum[j]^2-b*sum[j])-(2a*sum[j]*sum[i]))+(a*sum[i]^2+b*sum[i]+c) 我们可以把每个决策映射到平面上的一个点 其中x坐标为(a*sum[j]^2-b*sum[j])代表此决策的固定价值(与转移到哪无关) y坐标为-(2a*sum[j]) 代表此决策的潜在价值(

[APIO2010]特别行动队 --- 斜率优化DP

[APIO2010]特别行动队 题面很直白,就不放了. 太套路了,做起来没点感觉了. \(dp(i)=dp(j)+a*(s(i)-s(j))^{2}+b*(s(i)-s(j))+c\) 直接推出一个斜率优化的式子上单调队列就好了 时间/空间复杂度:\(O(n)\) #include<cstdio> #define sid 1000500 #define ri register int #define ll long long #define dd double using namespace

BZOJ 1911 特别行动队(斜率优化DP)

应该可以看出这是个很normal的斜率优化式子.推出公式搞一搞即可. # include <cstdio> # include <cstring> # include <cstdlib> # include <iostream> # include <vector> # include <queue> # include <stack> # include <map> # include <set>

bzoj1911[Apio2010]特别行动队 斜率优化dp

1911: [Apio2010]特别行动队 Time Limit: 4 Sec  Memory Limit: 64 MBSubmit: 5057  Solved: 2492[Submit][Status][Discuss] Description Input Output Sample Input 4 -1 10 -20 2 2 3 4 Sample Output 9 HINT dp[i]=dp[j]+a*x*x+b*x+cx=sum[i]-sum[j] 证明单调性假设对于i点 k<j且j的决策

BZOJ 1911: [Apio2010]特别行动队 [斜率优化DP]

1911: [Apio2010]特别行动队 Time Limit: 4 Sec  Memory Limit: 64 MBSubmit: 4142  Solved: 1964[Submit][Status][Discuss] Description Input Output Sample Input 4 -1 10 -20 2 2 3 4 Sample Output 9 HINT f[i]=max{f[j]+...} 随便一化就好了 (a*(s[k]*s[k]-s[j]*s[j])+f[k]-f[

APIO 2010 特别行动队 | 斜率优化DP

luogu 3628 si表示序列的前缀和f(i)表示将序列的前i个划分若干段的最大价值f(i)= max{f(j)+a∗(si−sj)2+b∗(si−sj)+c},1≤j<i    = max{−2a*sj*si+f(j)+a*sj*sj−b*sj}+a*si*si+b*si+c,1≤j<i 1 #include <cstdio> 2 #include <string> 3 4 typedef long long ll; 5 6 ll a, b, c; 7 8 ll

[bzoj 1911][Apio 2010]特别行动队(斜率优化DP)

题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1911 分析: 首先可以的到裸的方程f[i]=max{f[j]+a*(Si-Sj)^2+b*(Si-Sj)+c} 0<j<i 简化一下方程,我们知道对于一次项,最后结果肯定是b*Sn 所以可以写成f[i]=max{f[j]+a*(Si-Sj)^2+c} 0<j<i 我们不妨设0<x<y<i,且x比y优 即f[x]+a*(Si-Sx)^2+c>f[y]+a*

【uoj#244】[UER #7]短路 CDQ分治+斜率优化dp

题目描述 给出 $(2n+1)\times (2n+1)$ 个点,点 $(i,j)$ 的权值为 $a[max(|i-n-1|,|j-n-1|)]$ ,找一条从 $(1,1)$ 走到 $(2n+1,2n+1)$ 的路径,使得经过的点(包括起点和终点)权值和最小.求这个权值和. 输入 第一行一个正整数 $n$ . 第二行 $n+1$ 个正整数 $a[0],a[1],…,a[n]$ ,表示从内到外每层的中继器的延时值. 输出 输出一行一个数表示改造后的最短引爆时间. 样例输入 99 5 3 7 6 9