决策单调性
决策单调性: 我的理解就是 你每一个F[i] 用于更新它的 F[j] 的 j 的大小,一定不比 F[i-1] 的要靠前。 这就意味着我们可以去维护 一个决策点他作为哪一段区间的决策点时最优
维护时 我们可以 用二分来维护 核心代码:
while(Q[h1].r<j) h1++; // find the point that can be used to update this point F[i].push_back(getans(i,j,Q[h1].id)); while(t2>=h2&&getans(i+1,T[t2].l,T[t2].id)>getans(i+1,T[t2].l,j)) // pop all the element that is useless to update the following points T[t2].l=1,T[t2].r=n,T[t2].id=0,t2--; // initally int l=T[t2].l,r=T[t2].r,ans=r+1; while(l<=r)// find the point that is 'special' { int mid=(l+r)>>1; if(getans(i+1,mid,T[t2].id)>getans(i+1,mid,j)) ans=mid,r=mid-1; else l=mid+1; } if(ans==n+1) continue; T[t2].r=ans-1; T[++t2]=(node){ans,n,j}; // update and push_in the new element
xjoi shoes
1 #include <bits/stdc++.h> 2 #define int long long 3 #define N 100010 4 #define ls c[x][0] 5 #define rs c[x][1] 6 using namespace std; 7 typedef long long ll; 8 inline int read() 9 { 10 int x=0,f=1; char ch=getchar(); 11 while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();} 12 while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();} 13 return x*f; 14 } 15 struct shoes_pair 16 { 17 int a,b; 18 }S[N]; 19 struct node 20 { 21 int l,r,id; 22 }Q[N],T[N]; 23 void print(vector <ll> a){ for(int i=0;i<a.size();i++) cout << a[i] << " "; cout << endl;} 24 inline bool cmp(const shoes_pair a,const shoes_pair b) 25 { 26 return (double(a.a+a.b)/2.0)<(double(b.a+b.b)/2.0); 27 } 28 int n,Rt[N],c[N*36][2],ansrl[N*36],size[N*36],anslr[N*36],tot; 29 int V[N*3],k,h1,t1,h2,t2; map <int,int> M; vector <ll> F[N]; 30 inline void cpy(int x,int y) 31 { 32 c[x][0]=c[y][0]; c[x][1]=c[y][1]; 33 size[x]=size[y]; anslr[x]=anslr[y]; 34 ansrl[x]=ansrl[y]; 35 } 36 inline void updata(int x,int l,int r,int mid) 37 { 38 ansrl[x]=ansrl[ls]+ansrl[rs]+size[rs]*(V[mid+1]-V[l]); 39 anslr[x]=anslr[ls]+anslr[rs]+size[ls]*(V[r]-V[mid]); 40 size[x]=size[ls]+size[rs]; 41 } 42 int built(int x,int l,int r,int rt) 43 { 44 int g=++tot; cpy(g,rt); 45 if(l==r) 46 { 47 ansrl[g]=anslr[g]=0; 48 size[g]++; return g; 49 } int mid=(l+r)>>1; 50 if(mid>=x) c[g][0]=built(x,l,mid,c[g][0]); 51 if(mid<x) c[g][1]=built(x,mid+1,r,c[g][1]); 52 updata(g,l,r,mid); 53 return g; 54 } 55 ll querylr(int x,int l,int r,int rt1,int rt2) 56 { 57 if(!(size[rt2]-size[rt1])) return 0; if(l>r) return 0; int mid=(l+r)>>1; 58 if(x==mid) return anslr[c[rt2][0]]-anslr[c[rt1][0]]; 59 if(x<=mid) return querylr(x,l,mid,c[rt1][0],c[rt2][0]); 60 return anslr[c[rt2][0]]-anslr[c[rt1][0]]+(size[c[rt2][0]]-size[c[rt1][0]])*(V[x]-V[mid])+ 61 querylr(x,mid+1,r,c[rt1][1],c[rt2][1]); 62 } 63 ll queryrl(int x,int l,int r,int rt1,int rt2) 64 { 65 if(!(size[rt2]-size[rt1])) return 0; if(l>r) return 0; int mid=(l+r)>>1; 66 if(x==mid+1) return ansrl[c[rt2][1]]-ansrl[c[rt1][1]]; 67 if(x>mid) return queryrl(x,mid+1,r,c[rt1][1],c[rt2][1]); 68 return ansrl[c[rt2][1]]-ansrl[c[rt1][1]]+(size[c[rt2][1]]-size[c[rt1][1]])*(V[mid+1]-V[x])+ 69 queryrl(x,l,mid,c[rt1][0],c[rt2][0]); 70 } 71 int getmid(int g,int l,int r,int rt1,int rt2) 72 { 73 int mid=(l+r)>>1; if(l==r) return l; 74 if(size[c[rt2][0]]-size[c[rt1][0]]>=g) return getmid(g,l,mid,c[rt1][0],c[rt2][0]); 75 return getmid(g-size[c[rt2][0]]+size[c[rt1][0]],mid+1,r,c[rt1][1],c[rt2][1]); 76 } 77 inline ll getdis(int l,int r) 78 { 79 if(l>r) return 0; 80 int alls=size[Rt[r]]-size[Rt[l-1]]; 81 int x=getmid(alls>>1,1,V[0],Rt[l-1],Rt[r]); 82 ll ret=querylr(x,1,V[0],Rt[l-1],Rt[r])+queryrl(x,1,V[0],Rt[l-1],Rt[r]); 83 return ret; 84 } 85 inline ll getans(int i,int j,int t) 86 { 87 ll ret=F[i-1][t]+getdis(t+1,j); 88 return ret; 89 } 90 signed main() 91 { 92 n=read(); k=read(); for(int i=1;i<=n;i++) 93 S[i].a=read(),S[i].b=read(), 94 V[++V[0]]=S[i].a,V[++V[0]]=S[i].b; 95 sort(S+1,S+1+n,cmp); sort(V+1,V+1+V[0]); 96 V[0]=unique(V+1,V+1+V[0])-V-1; 97 for(int i=1;i<=V[0];i++) M[V[i]]=i; 98 for(int i=1;i<=n;i++) S[i].a=M[S[i].a],S[i].b=M[S[i].b]; 99 for(int i=1;i<=n;i++) 100 Rt[i]=built(S[i].a,1,V[0],Rt[i-1]), 101 Rt[i]=built(S[i].b,1,V[0],Rt[i]); 102 F[0].push_back(0); ll ans=10000000000000000ll; 103 for(int i=1;i<=n;i++) F[0].push_back(ans); 104 h1=1; t1=0; Q[++t1]=(node){1,n,0}; 105 for(int i=1;i<=k;i++) 106 { 107 F[i].push_back(0); h2=1; t2=0; 108 T[++t2]=(node){1,n,0}; 109 for(int j=1;j<=n;j++) 110 { 111 while(Q[h1].r<j) h1++; 112 F[i].push_back(getans(i,j,Q[h1].id)); 113 while(t2>=h2&&getans(i+1,T[t2].l,T[t2].id)>getans(i+1,T[t2].l,j)) 114 T[t2].l=1,T[t2].r=n,T[t2].id=0,t2--; 115 int l=T[t2].l,r=T[t2].r,ans=r+1; 116 while(l<=r) 117 { 118 int mid=(l+r)>>1; 119 if(getans(i+1,mid,T[t2].id)>getans(i+1,mid,j)) 120 ans=mid,r=mid-1; 121 else l=mid+1; 122 } 123 if(ans==n+1) continue; 124 T[t2].r=ans-1; T[++t2]=(node){ans,n,j}; 125 } 126 ans=min(ans,F[i][n]); 127 t1=t2; h1=h2; 128 for(int j=h1;j<=t1;j++) Q[j]=T[j]; 129 } 130 cout << ans << endl; 131 132 return 0; 133 }
bzoj 诗人小G
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 typedef long double ldb; 5 const ll limit=(ll)1e18; 6 inline int read() 7 { 8 int x=0,f=1; char ch=getchar(); 9 while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();} 10 while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();} 11 return x*f; 12 } 13 struct node 14 { 15 int id,l,r; 16 }Q[100010]; 17 ldb F[100010]; 18 ll sum[100010]; 19 int t,n,L,p,hd,tl; char sd[50]; 20 ldb qpow(ldb bas,int pw) 21 { 22 ldb ret=1; 23 while(pw--) 24 { 25 ret*=bas; 26 } 27 return ret; 28 } 29 ldb get(int x,int y) 30 { 31 ldb ret=F[y]+qpow(fabs(sum[x]-sum[y]+x-y-1-L),p); 32 return ret; 33 } 34 int main() 35 { 36 //freopen("read.in","r",stdin); 37 scanf("%d",&t); 38 while(t--) 39 { 40 scanf("%d%d%d",&n,&L,&p); 41 sum[0]=0; 42 for(int i=1;i<=n;i++) 43 { 44 scanf("%s",sd); 45 sum[i]=sum[i-1]+strlen(sd); 46 } 47 hd=1; tl=0; Q[++tl]=(node){0,1,n}; 48 for(int i=1;i<=n;i++) 49 { 50 while(Q[hd].r<i) hd++; 51 F[i]=get(i,Q[hd].id); 52 while(get(Q[tl].l,i)<get(Q[tl].l,Q[tl].id)&&tl>=hd) Q[tl].id=0,Q[tl].l=1,Q[tl].r=n,tl--; 53 int lls=Q[tl].l,rr=Q[tl].r,ans=rr+1; 54 while(lls<=rr) 55 { 56 int mid=(lls+rr)>>1; 57 if(get(mid,i)<get(mid,Q[tl].id)) 58 ans=mid,rr=mid-1; 59 else lls=mid+1; 60 } 61 if(ans==n+1) continue; 62 Q[tl].r=ans-1; Q[++tl].l=ans; Q[tl].r=n; Q[tl].id=i; 63 } 64 if(F[n]>limit) printf("Too hard to arrange\n"); 65 else printf("%.0Lf\n",F[n]); 66 puts("--------------------"); 67 } 68 return 0; 69 }
bzoj 2214 (好像写假了 死活过不去?? 本地拍并没有什么问题。。)
dp方程为 pi= a[j]-a[i]+sqrt(i-j)
注意到函数f(x)=sqrt(x)-sqrt(x-1)单调递减 所以若k<j<i且对于i而言j比k优 则k没用了 决策单调能从此观察出来
1 #include <bits/stdc++.h> 2 #define N 1000010 3 using namespace std; 4 typedef long long ll; 5 6 struct node 7 { 8 int l,r,id; 9 }Q[N]; 10 ll a[N],n,hd,tl,F[N],gg[N]; 11 inline ll get(int i,int j) 12 { 13 if(i<j) return 0; 14 return a[j]+gg[i-j]-a[i]; 15 } 16 int main() 17 { 18 // freopen("read.in","r",stdin); 19 scanf("%lld",&n); for(int i=1;i<=n;i++) scanf("%lld",&a[i]); 20 hd=1; tl=0; Q[++tl]=(node){1,n,1}; 21 for(int i=1;i*i<=N-10;i++) gg[i*i]=i; 22 for(int i=1;i*i<=N-10;i++) 23 { 24 int j=i*i-1; while(j>0&&!gg[j]) gg[j]=i,j--; 25 } 26 //for(int i=1;i<=N-10;i++) printf("%d ",gg[i]); printf("\n"); 27 for(int i=1;i<=n;i++) 28 { 29 while(Q[hd].r<i) hd++; 30 F[i]=max(F[i],get(i,Q[hd].id)); //printf("%d %d\n",Q[hd].id,get(i,Q[hd].id)); 31 while(tl>=hd&&get(Q[tl].l,Q[tl].id)<get(Q[tl].l,i)) 32 Q[tl].id=1,Q[tl].l=1,Q[tl].r=n,tl--; 33 int l=Q[tl].l,r=Q[tl].r,ans=0; 34 while(l<=r) 35 { 36 int mid=(l+r)>>1; 37 if(get(mid,Q[tl].id)>get(mid,i)) 38 ans=mid,l=mid+1; 39 else r=mid-1; 40 } 41 if(ans==n) continue; 42 Q[tl].r=ans; Q[++tl]=(node){ans+1,n,i}; 43 } 44 hd=1; tl=0; Q[++tl]=(node){1,n,1}; 45 for(int i=1;i<=n/2;i++) swap(a[i],a[n-i+1]); 46 for(int i=1;i<=n;i++) 47 { 48 while(Q[hd].r<i) hd++; 49 F[n-i+1]=max(F[n-i+1],get(i,Q[hd].id)); //printf("%d %d\n",Q[hd].id,get(i,Q[hd].id)); 50 51 int l=Q[tl].l,r=Q[tl].r,ans=0; 52 while(l<=r) 53 { 54 int mid=(l+r)>>1; 55 if(get(mid,Q[tl].id)>get(mid,i)) 56 ans=mid,l=mid+1; 57 else r=mid-1; 58 } 59 if(ans==n) continue; 60 Q[tl].r=ans; Q[++tl]=(node){ans+1,n,i}; 61 } 62 for(int i=1;i<=n;i++) printf("%lld\n",F[i]); 63 }