标签:iss ict break from str hdu possible ble script
o o o o o o o o o o o o o o o o o o /F\ /F\ /F\ /F\ /F\ /F\ /F\ /F\ /F\ /F\ /F\ /F\ /F\ /F\ /F\ /F\ /F\ /F/ \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \
o o o | o o o o | o o o o o o | o o o o o /F\ /F\ /F\ | /F\ /F\ /F\ /F\ | /F\ /F\ /F\ /F\ /F\ /F\ | /F\ /F\ /F\ /F\ /F/ \ / \ / \ | / \ / \ / \ / \ | / \ / \ / \ / \ / \ / \ | / \ / \ / \ / \ / \
2 5 2 1 4 3 2 5 5 2 5 4 3 2 1
Case #1: 31 Case #2: No solution
题意:有n个数,划分为多个部分,如果M份,每份不能多于L个。每一个数有一个h[i],每份最右边的那个数要大于前一份最右边的那个数。
设每份最右 边的数为b[i]。求最大的sum{b[i]2 - b[i - 1]},1≤i≤M,当中b[0] = 0。
题解:dp[i]表示前i个数能达到的最大值。dp[i]=max(dp[i],dp[j]+h[i]*h[i]-h[j]),i-L<=j<i.
线段树优化:先排个序。按h从小到大排。相等的pos大的在前。这是为了保证严格升序。
然后逐个插入,更新a[i].pos位置的单点值,再维护区间最大值,具体见代码。
#include<cstring> #include<cstdio> #include<iostream> #include<algorithm> #include<cmath> #include<queue> #define lson l,mid,idx<<1 #define rson mid+1,r,idx<<1|1 #define lc idx<<1 #define rc idx<<1|1 #define N 100010 #define ll long long using namespace std; int n,m; struct node { int pos; ll num; } a[N]; ll tree[N<<2]; void build(int l,int r,int idx) { tree[idx]=-1; if(r==l)return; int mid=(l+r)>>1; build(lson); build(rson); } void update(int l,int r,int idx,int x,ll k) {///把x位置的值更新 if(l==r) { tree[idx]=max(tree[idx],k); return; } int mid=(l+r)>>1; if(x<=mid)update(lson,x,k); else update(rson,x,k); tree[idx]=max(tree[lc],tree[rc]); } ll query(int l,int r,int idx,int x,int y) { if(l>=x&&y>=r) { return tree[idx]; } int mid=(l+r)>>1; ll ans=-1; if(x<=mid)ans=max(ans,query(lson,x,y)); if(y>mid) ans=max(ans,query(rson,x,y)); return ans; } bool cmp(node a,node b) { if(a.num==b.num)return a.pos>b.pos; return a.num<b.num; } int main() { //freopen("test.in","r",stdin); int t; cin>>t; int ca=1; while(t--) { scanf("%d%d",&n,&m); for(int i=1; i<=n; i++) { scanf("%I64d",&a[i].num); a[i].pos=i+1; } sort(a+1,a+n+1,cmp); n++; build(1,n,1); update(1,n,1,1,0); ll ans=-1; for(int i=1; i<n; i++) { int l=(a[i].pos-m)>0?(a[i].pos-m):1,r=a[i].pos-1;///能一组的最左区间和最右区间-1 ll it=query(1,n,1,l,r); if(it==-1&&a[i].pos==n) {///-1表示分不了组 break; } if(it==-1) continue; it+=a[i].num*a[i].num; if(a[i].pos==n) {//已经更新到n了。直接跳出 ans=it; break; } update(1,n,1,a[i].pos,it-a[i].num);//减去当前a[i].num,非常巧妙 } printf("Case #%d: ",ca++); if(ans==-1)printf("%s\n","No solution" ); else printf("%I64d\n",ans ); } return 0; }
hdu 4719 Oh My Holy FFF(dp线段树优化)
标签:iss ict break from str hdu possible ble script
原文地址:http://www.cnblogs.com/jzdwajue/p/6803956.html