HDU4719-Oh My Holy FFF (DP line segment tree optimization)
Oh My Holy FFFTime Limit: 5000/2500 MS (Java/Others) Memory Limit: 65535/65535 K (Java/Others)
Total Submission (s): 606 Accepted Submission (s): 141
Problem DescriptionN soldiers from the famous "* FFF * army" is standing in a line, from left to right.
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\/ \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \
You, as the captain of * FFF *, want to divide them into smaller groups, but each group shoshould still be continous in the original line. Like this:
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\/ \ / \ / \ | / \ / \ / \ / \ | / \ / \ / \ / \ / \ / \ | / \ / \ / \ / \ / \
In your opinion, the number of soldiers in each group shocould be no more than L.
Meanwhile, you want your division be "holy ". since the soldier may have different heights, you decide that for each group should t the first one, its last soldier (which is the rightmost one) shocould be strictly taller than the previous group's last soldier. that is, if we set bi as the height of the last soldier in group I. then for I> = 2, there shoshould be bi> bi-1.
You give your division a score, which is calculated as, b0 = 0 and 1 <= k <= M, if there are M groups in total. Note that M can equal to 1.
Given the heights of all soldiers, please tell us the best score you can get, Z keys? Http://www.bkjia.com/kf/ware/vc/ "target =" _ blank "class =" keylink "> memory + Memory + IDw9IDEwPHN1cD41PC9zdXA + KQoKIAo8YnI + Memory =" Case # X: "first, then output the best score.
Sample Input
25 21 4 3 2 55 25 4 3 2 1
Sample Output
Case #1: 31Case #2: No solution
Question:
N (n <1e5) Individual lines, cut it into several heaps, the length of each heap must not exceed l (l <1e5 ), in addition, the height of the rightmost person in each stack is higher than that of the rightmost person in the previous stack. For each scheme, its score is SUM (B [k] ^ 2-b [k-1]) B [k] is the highest score required for the height of the rightmost person in the k heap.Ideas:
The simple DP is DP [I] = max (DP [j]-B [j]) + B [I] * B [I] (I-l <= j <= i-1) but this will time out (O (n ^ 2 )) we can find that every time DP [I] is to find the maximum value of the interval [I-l, I-1] DP [j]-B [j], so we can use the line segment tree optimization, at this time also need to solve a problem: is how to ensure that each request DP [I] to ensure that the interval [I-l, I-1] of everyone's height is shorter than their own? You can sort the numbers first, so that short people can select the numbers first. If the height is the same, the numbers will be selected first. In this way, there will be no conflict (when updating a single point ). You can perform single-point update for each query.
#include
#include
#include
#include
#include using namespace std;#define REP(_,a,b) for(int _=(a); _<=(b);++_)#define sz(s) (int)((s).size())typedef long long ll;const int maxn = 1e5+10;int n,l;ll dp[maxn];struct Num{ll h;int idx;Num(ll h = 0,int idx = 0):h(h),idx(idx){}friend bool operator < (Num a,Num b){if(a.h!=b.h) return a.h < b.h;else return a.idx > b.idx;}};vector
vN;struct node{int lson,rson;ll maxx;int mid(){return (lson+rson)>>1;}}tree[maxn*4];void pushUp(int rt){tree[rt].maxx = max(tree[rt<<1].maxx,tree[rt<<1|1].maxx);} void build(int L,int R,int rt){tree[rt].lson = L;tree[rt].rson = R;tree[rt].maxx = -1;if(L==R){return;}int mid = tree[rt].mid();build(L,mid,rt<<1);build(mid+1,R,rt<<1|1);}void init(){vN.clear();memset(dp,-1,sizeof dp);}void update(int pos,int l,int r,int rt,ll x){if(l==r){tree[rt].maxx = x;return;}int mid = tree[rt].mid();if(pos<=mid){update(pos,l,mid,rt<<1,x);}else{update(pos,mid+1,r,rt<<1|1,x);}pushUp(rt);}ll query(int L,int R,int l,int r,int rt){if(L <=l && R >= r){return tree[rt].maxx;}int mid = tree[rt].mid();ll ret;bool flag = false;if(L <= mid){ret = query(L,R,l,mid,rt<<1);flag = true;}if(R > mid){if(flag){ret = max(ret,query(L,R,mid+1,r,rt<<1|1));}else{ret = query(L,R,mid+1,r,rt<<1|1);}}return ret;}void input(){scanf("%d%d",&n,&l);for(int i = 1; i <= n; i++){ll h;scanf("%I64d",&h);vN.push_back(Num(h,i));}sort(vN.begin(),vN.end());build(0,n,1);}void solve(){update(0,0,n,1,0);REP(_,0,sz(vN)-1) {int ni = vN[_].idx;ll nh = vN[_].h;ll tm = query(max(ni-l,0),ni-1,0,n,1);if(tm>=0){dp[ni] = tm+nh*nh;update(ni,0,n,1,dp[ni]-nh);}if(ni==n) break;}if(dp[n]<=0){printf("No solution\n");}else{printf("%I64d\n",dp[n]);}}int main(){int ncase,T=1;cin >> ncase;while(ncase--){init();input();printf("Case #%d: ",T++);solve();}return 0;}