孤独一生
Time Limit:10000MS Memory Limit:165536K
Total Submit:23 Accepted:11
Case Time Limit:1000MS
Description
Input
第一行一个数N。
第二行N个整数Hi。
Output
一行一个整数,表示最小的总体力值。
Sample Input
3
1 3 1
Sample Output
4
Hint
对于10%的数据N<=20。
对于20%的数据N<=100。
对于50%的数据N<=5000。
对于100%的数据1<=N<=500000。
设f[i][j]表示第一个集合结尾是i,第二个集合结尾是j,我们考虑到这两个集合没有本质区别,所以假设i>=j
这是O(N2)
设g[i]=f[i][i-1],sum[i]=sum[i-1]+abs(h[i]-h[i-1]),我们就只需要枚举前面的g[j]就行了
转移为g[i]=min{g[j]+sum[i-1]-sum[j]+abs(h[i]-h[j-1)}
答案就是min(g[i]+sum[n]-sum[i])
绝对值就用树状数组去就可以了
code:
1 #include<cstdio> 2 #include<iostream> 3 #include<cmath> 4 #include<cstring> 5 #include<algorithm> 6 #define maxn 500005 7 #define lowbit(x) ((x)&(-(x))) 8 #define inf 4557430888798830399LL 9 using namespace std; 10 typedef long long int64; 11 char ch; 12 int n,tot,h[maxn],pos[maxn]; 13 int64 sum[maxn],f[maxn],ans; 14 struct DATA{ 15 int val,num; 16 }list[maxn]; 17 bool cmp(DATA a,DATA b){return a.val<b.val;} 18 struct bit{ 19 int64 val[maxn]; 20 void init(){memset(val,63,sizeof(val));} 21 void insert(int x,int64 v){for (;x<=tot;x+=lowbit(x)) val[x]=min(val[x],v);} 22 int64 query(int x){ 23 int64 ans=inf; 24 for (;x;x-=lowbit(x)) ans=min(ans,val[x]); 25 return ans; 26 } 27 }T1,T2; 28 bool ok; 29 void read(int &x){ 30 for (ok=0,ch=getchar();!isdigit(ch);ch=getchar()) if (ch=='-') ok=1; 31 for (x=0;isdigit(ch);x=x*10+ch-'0',ch=getchar()); 32 if (ok) x=-x; 33 } 34 int main(){ 35 read(n),n++; 36 for (int i=2;i<=n;i++) read(h[i]); 37 for (int i=1;i<=n;i++) sum[i]=sum[i-1]+abs(h[i]-h[i-1]); 38 for (int i=1;i<=n;i++) list[i]=(DATA){h[i],i}; 39 sort(list+1,list+n+1,cmp); 40 pos[1]=tot=1; 41 for (int i=2;i<=n;i++){ 42 if (list[i].val!=list[i-1].val) tot++; 43 pos[list[i].num]=tot; 44 } 45 T1.init(),T2.init(); 46 memset(f,63,sizeof(f)); 47 f[1]=0,T1.insert(pos[1],f[1]-sum[1]-h[0]),T2.insert(tot-pos[1]+1,f[1]-sum[1]+h[0]); 48 for (int i=2;i<=n;i++){ 49 f[i]=sum[i-1]+min(h[i]+T1.query(pos[i]),-h[i]+T2.query(tot-pos[i])); 50 T1.insert(pos[i-1],f[i]-sum[i]-h[i-1]); 51 T2.insert(tot-pos[i-1]+1,f[i]-sum[i]+h[i-1]); 52 } 53 ans=inf; 54 for (int i=1;i<=n;i++) ans=min(ans,f[i]+sum[n]-sum[i]); 55 printf("%I64d ",ans); 56 return 0; 57 }