【bzoj2149】拆迁队

来源:互联网 发布:中国行政区数据库 编辑:程序博客网 时间:2024/03/28 22:21

似乎又是一道cdq维护dp

这题首先要按照d[i]=a[i]-i的值分层dp。

在cdq分治中,相当于前一层dp为修改,当前层为询问。

考虑如何维护[l,mid]的修改对于[mid+1,r]的询问的影响。

列出dp方程发现只要寻找最小值即可。

然后就在维护的凸包上三分最小值的位置就好。

#include <bits/stdc++.h>#define gc getchar()#define N 120009#define mid (l+r>>1)#define ll long longusing namespace std;const ll inf=0x3f3f3f3f3f3f3f3f;ll n,m,a[N],b[N],d[N],f[N],sta[N],top,g[N];vector<ll> p[N];struct node{ll x,y,pos,k;node(ll pos=0,ll k=0):pos(pos),k(k){x=d[pos],y=g[pos]-a[pos]*pos-a[pos]+(pos+1)*pos/2;}bool operator <(const node &rhs) const{return pos<rhs.pos;}}q[N],now[N],st[N];bool cmp(const node &lhs,const node &rhs){return d[lhs.pos]<d[rhs.pos]||(d[lhs.pos]==d[rhs.pos]&&!lhs.k);}ll read(){ll x=1;char ch;while (ch=gc,ch<'0'||ch>'9') if (ch=='-') x=-1;ll s=ch-'0';while (ch=gc,ch<='9'&&ch>='0') s=s*10+ch-'0';return s*x;}void solve(ll l,ll r){if (l==r){if (q[l].k)g[q[l].pos]+=a[q[l].pos]+b[q[l].pos]+(q[l].pos-1)*q[l].pos/2;return;}solve(l,mid);ll num=0;for (ll i=l;i<=mid;i++) if (!q[i].k) now[++num]=q[i];//modify in [l,mid]for (ll i=mid+1;i<=r;i++) if (q[i].k) now[++num]=q[i];//qry in [mid+1,r]sort(now+1,now+num+1,cmp);//sort for dtop=0;for (ll i=1;i<=num;i++)//d is increasing{#define j now[i]if (!j.k)//slope optimization{while (top>=2&&1.0*(j.y-st[top].y)*(st[top].x-st[top-1].x)<1.0*(st[top].y-st[top-1].y)*(j.x-st[top].x))top--;st[++top]=j;}else{ll L=1,R=top,len,mid_l,mid_r;//divide into three parts for the bestwhile (R-L>4){len=(R-L)/3,mid_l=L+len,mid_r=R-len;if (st[mid_l].x*j.pos+st[mid_l].y>st[mid_r].x*j.pos+st[mid_r].y) L=mid_l;else R=mid_r;//min}while (L<=R) g[j.pos]=min(g[j.pos],st[L].x*j.pos+st[L].y),++L;}#undef j}solve(mid+1,r);}int main(){n=read();for (ll i=1;i<=n;i++) a[i]=read(),d[i]=a[i]-i,sta[i]=g[i]=inf;for (ll i=1;i<=n;i++) b[i]=read();for (ll i=1;i<=n;i++){if (d[i]<0) continue;f[i]=upper_bound(sta+1,sta+n+1,d[i])-sta;p[f[i]].push_back(i);sta[f[i]]=min(sta[f[i]],d[i]);}p[0].push_back(0);for (ll i=1;;i++){if (p[i].empty()){ll ret=inf;for (ll j=0,k;j<(ll)p[i-1].size();j++){k=p[i-1][j];ret=min(ret,g[k]+(a[k]*2+n-k+1)*(n-k)/2);}printf("%lld %lld\n",i-1,ret);break;}m=0;for (ll j=0;j<(ll)p[i-1].size();j++) q[++m]=node(p[i-1][j],0);for (ll j=0;j<(ll)p[i].size();j++) q[++m]=node(p[i][j],1);sort(q+1,q+m+1);solve(1,m);}return 0;}


原创粉丝点击