标签: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/ \ / \ / \ | / \ / \ / \ / \ | / \ / \ / \ / \ / \ / \ | / \ / \ / \ / \ / \
, b0 = 0 and 1 <= k <= M, if there are M groups in total. Note that M can equal to 1.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