标签:VID otto tree scanf NPU source arch alc com
Time Limit: 5000/2500 MS (Java/Others) Memory Limit: 65535/65535 K (Java/Others)
Total Submission(s): 1368 Accepted Submission(s): 394
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\
/ \ / \ / \ | / \ / \ / \ / \ | / \ / \ / \ / \ / \ / \ | / \ / \ / \ / \ / \
朴素的DP 是 DP[i] = max(DP[j] - b[j]) + b[i]*b[i] ( i-l <= j <= i-1 ) 可是这样会超时(O(n^2)) 能够发现每次求DP[i] 的时候 实际就是求 区间[i-l,i-1] DP[j]-b[j]的最大值,因此能够利用线段树优化。此时还须要解决一个问题:就是怎样保证每次求DP[i]的时候保证区间[i-l,i-1] 的每一个人的身高都是比自己矮的? 能够进行先排序。让矮的人先选,假设身高一样就让序号在后的先选,这样就不会有冲突了(单点更新的时候)。 每次查询的时候单点更新就可以。
#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; }
HDU4719-Oh My Holy FFF(DP线段树优化)
标签:VID otto tree scanf NPU source arch alc com
原文地址:https://www.cnblogs.com/DWVictor/p/11218956.html