bzoj2149拆迁队 斜率优化dp+分治
2149: 拆迁队
Time Limit: 10 Sec Memory Limit: 259 MBSubmit: 397 Solved: 177
[Submit][Status][Discuss]
Description
lanxisi带领着他的拆迁队来整治一个街道。这个街道由N个旧房子组成,从左到右编号为1..N。每个旧房子i有一个正整数的美观度Ai。
lanxisi希望整个街道从左到右美观度严格递增,也就是保证Ai<Aj(i<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。
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 }
If you live in the echo,
your heart never beats as loud.
如果你生活在回声里,
你的心跳声永远不会轰鸣作响。