BZOJ 1099([POI2007]树Drz-9次线段树&分类讨论+线段树与插入顺序维护2个参数)

来源:互联网 发布:淘宝隐形降权怎样恢复 编辑:程序博客网 时间:2024/06/09 14:43

1099: [POI2007]树Drz

Time Limit: 15 Sec  Memory Limit: 162 MB
Submit: 142  Solved: 55
[Submit][Status]

Description

CDQZ是一个偏远的小学校,FGD在学校里中了一排树。他却不喜欢这些树的顺序,因为他们高高矮矮显得那么参差不齐。 FGD定义这些树的不整齐程度为相邻两树的高度差的和。设树高分别为h1,h2,h3,…,hn。那么不整齐程度定义为:|h1-h2|+|h2-h3|+……+|hn-1-hn|。不过,重新栽种这些树是一件麻烦的事情,所以FGD最多只想交换其中两个树的位置。现在请你帮助他,他应该怎么交换使得整个一排树的不整齐程度最小。

Input

第一行包含一个整数n(2<=n<= 50000),接下来第二行包含n个正整数h1,h2,h3,…,hn,分别表示树的高度。(1<=hi<=100000000)

Output

应该包含n行,每行一个整数,第i行表示若交换的其中一棵树编号为i,则能获得的最小不整齐程度为多少。

Sample Input

样例输入1
5
7 4 5 2 5

样例输入2
5
1 2 3 4 5

Sample Output

样例输出1
7
7
8
7
7

样例输出2
4
4
4
4
4

HINT

Source

[Submit][Status]



本题是丧心病狂的分类讨论

显然如果考虑换hi时,最优解是与hj换

那么hi有最小,次小,最大(相对i两侧的树)3种情况,hj也有(相对j两侧)

故可分为3*3种情况

线段树的插入顺序维护hj的情况,符合条件扔进线段树中。

至于hi当然直接在线段树上找。

列交换代价差值公式,分别分析9种情况。

特:

注意先把hi,hi左右2侧最大值,左右2侧最小值排序离散化插入树中,因为插入树中时按的是hi的值



#include<cstdio>#include<cstring>#include<cstdlib>#include<algorithm>#include<functional>#include<iostream>#include<cmath>#include<cctype>#include<ctime>#include<vector>using namespace std;#define For(i,n) for(int i=1;i<=n;i++)#define Fork(i,k,n) for(int i=k;i<=n;i++)#define Rep(i,n) for(int i=0;i<n;i++)#define ForD(i,n) for(int i=n;i;i--)#define ForkD(i,k,n) for(int i=n;i>=k;i--)#define RepD(i,n) for(int i=n;i>=0;i--)#define Forp(x) for(int p=pre[x];p;p=next[p])#define Forpiter(x) for(int &p=iter[x];p;p=next[p])  #define Lson (x<<1)#define Rson ((x<<1)+1)#define MEM(a) memset(a,0,sizeof(a));#define MEMI(a) memset(a,127,sizeof(a));#define MEMi(a) memset(a,128,sizeof(a));#define INF (2139062143)#define F (100000007)#define MAXN (50000+10)#define MAXH (100000000+10) long long mul(long long a,long long b){return (a*b)%F;}long long add(long long a,long long b){return (a+b)%F;}long long sub(long long a,long long b){return (a-b+(a-b)/F*F+F)%F;}typedef long long ll;int n,pos[MAXN],lpos[MAXN],rpos[MAXN],himinpos[MAXN],himaxpos[MAXN];ll h[MAXN],himax[MAXN],himin[MAXN],ans[MAXN],v[MAXN];pair<ll,int> h2[MAXN];class SegmentTree{ll a[MAXN*4],minv[MAXN*4];int n;public:SegmentTree(){MEM(a) MEM(minv) }SegmentTree(int _n):n(_n){MEM(a) MEM(minv) }void mem(int _n){n=_n;MEMI(a) MEMI(minv)}int p,v; //set a[p]=vvoid set(int p,int v){this->p=p,this->v=v;_set(1,1,n);}void _set(int x,int L,int R){int M=(L+R)>>1;if (L==R) {a[x]=minv[x]=v;return;}else{if (p<=M) _set(Lson,L,M);else _set(Rson,M+1,R);} minv[x]=min(minv[Lson],minv[Rson]);}int ql,qr;ll query_min(int ql,int qr){this->ql=ql,this->qr=qr;if (ql>qr) return INF;return _query_min(1,1,n); }ll _query_min(int x,int L,int R){if (ql<=L&&R<=qr) return minv[x];ll ans=INF,M=(L+R)>>1;if (ql<=M) ans=min(ans,_query_min(Lson,L,M));if (M< qr) ans=min(ans,_query_min(Rson,M+1,R));return ans;}}S;int t_n;ll dis(int i,int j){return abs(h[i]-h[j]);}void pre_work(){MEM(ans)// 一个在首尾,另一个在非首尾,不相邻 Fork(i,3,n-1) {ll tmp=-dis(1,2)+dis(i,2)-v[i]+dis(1,i-1)+dis(1,i+1);ans[1]=min(ans[1],tmp);ans[i]=min(ans[i],tmp);}Fork(i,2,n-2) {ll tmp=-dis(n,n-1)+dis(i,n-1)-v[i]+dis(n,i-1)+dis(n,i+1);ans[n]=min(ans[n],tmp);ans[i]=min(ans[i],tmp);}// 无首尾,相邻 Fork(i,2,n-2){ll tmp=-dis(i,i-1)-dis(i+1,i+2)+dis(i+1,i-1)+dis(i,i+2); ans[i]=min(ans[i],tmp);ans[i+1]=min(ans[i+1],tmp);}//一个在首尾,另一个在非首尾,相邻 1и2 or (n-1) иn ll tmp=-dis(2,3)+dis(1,3);ans[1]=min(ans[1],tmp);ans[2]=min(ans[2],tmp);tmp=-dis(n-2,n-1)+dis(n-2,n);ans[n]=min(ans[n],tmp);ans[n-1]=min(ans[n-1],tmp);//首尾,不相邻tmp=-dis(1,2)-dis(n-1,n)+dis(n,2)+dis(1,n-1);ans[1]=min(ans[1],tmp);ans[n]=min(ans[n],tmp);}struct node{int i,flag;ll a;node(){}node(int _i,int _flag,ll _a):i(_i),flag(_flag),a(_a){}void print(){cout<<i<<':'<<flag<<' '<<a<<endl; } }a[3*MAXN];int m;int cmp1(const void* a,const void *b)// -1,0,1{node _a=*(node*)a,_b=*(node*)b;if (_a.a^_b.a) return _a.a-_b.a;else return _a.flag-_b.flag;} int cmp2(const void* a,const void *b)// case#1:0,-1  case#3:1,0  {node _a=*(node*)a,_b=*(node*)b;if (_a.a^_b.a) return _a.a-_b.a;else return _b.flag-_a.flag;} int fee_u[4][4]={{},{0,1,1,-2},{0,-1,1,0},{0,-1,-1,2}};void fee(int i,int j,int flagj,int flagi,ll &tmp,ll &add){tmp=-v[i]+fee_u[flagj+2][1]*himin[i]+fee_u[flagj+2][2]*himax[i]+fee_u[flagi+2][3]*h[i];add=-v[j]+fee_u[flagj+2][3]*h[j]+fee_u[flagi+2][1]*himin[j]+fee_u[flagi+2][2]*himax[j];}ll fee_tmp(int i,int flagj,int flagi){return -v[i]+fee_u[flagj+2][1]*himin[i]+fee_u[flagj+2][2]*himax[i]+fee_u[flagi+2][3]*h[i];}ll fee_add(int j,int flagj,int flagi){return -v[j]+fee_u[flagj+2][3]*h[j]+fee_u[flagi+2][1]*himin[j]+fee_u[flagi+2][2]*himax[j];}bool b[MAXN];void work1(const int flagj) // (-1,flagj){//cout<<"--------------------------\n";MEM(b)const int flagi=-1; qsort(a+1,m,sizeof(node),cmp2);S.mem(t_n);ForD(i,m){node now=a[i];if (now.flag==-1) {S.set(pos[now.i],fee_add(now.i,flagj,flagi)),b[pos[now.i]]=1;//cout<<"add:"<<pos[now.i]<<' '<<fee_add(now.i,flagj,flagi)<<endl; }else if (now.flag==0){ll tmp=fee_tmp(now.i,flagj,flagi),add;bool b1=0,b2=0;ll t1=0,t2=0;if (b[pos[now.i-1]]){b1=1;S.set(pos[now.i-1],INF);//cout<<"1del:"<<pos[now.i-1]<<endl; }if (b[pos[now.i+1]]){b2=1;S.set(pos[now.i+1],INF);//cout<<"1del:"<<pos[now.i+1]<<endl; }if (flagj==-1) add=S.query_min(1,rpos[himinpos[now.i]]);else if (flagj==0) add=S.query_min(lpos[himinpos[now.i]],rpos[himaxpos[now.i]]);else add=S.query_min(lpos[himaxpos[now.i]],t_n);//cout<<now.i<<' '<<flagj<<' '<<lpos[himaxpos[now.i]]<<' '<<tmp<<' '<<add<<endl; ans[now.i]=min(ans[now.i],tmp+add); if (b1){S.set(pos[now.i-1],fee_add(now.i-1,flagj,flagi));//cout<<"1add:"<<pos[now.i-1]<<endl; }if (b2){S.set(pos[now.i+1],fee_add(now.i+1,flagj,flagi));//cout<<"1add:"<<pos[now.i+1]<<endl; }}} }void work2(const int flagj) // (0,flagj){//cout<<"--------------------------\n";MEM(b)const int flagi=0; qsort(a+1,m,sizeof(node),cmp1);S.mem(t_n);ForD(i,m){node now=a[i];if (now.flag==1) {S.set(pos[now.i],fee_add(now.i,flagj,flagi)),b[pos[now.i]]=1;//cout<<"add:"<<pos[now.i]<<' '<<fee_add(now.i,flagj,flagi)<<endl; }else if (now.flag==-1) {S.set(pos[now.i],INF),b[pos[now.i]]=0;//cout<<"del:"<<pos[now.i]<<endl; }else if (now.flag==0){ll tmp=fee_tmp(now.i,flagj,flagi),add;bool b1=0,b2=0;ll t1=0,t2=0;if (b[pos[now.i-1]]){b1=1;S.set(pos[now.i-1],INF);//cout<<"1del:"<<pos[now.i-1]<<endl; }if (b[pos[now.i+1]]){b2=1;S.set(pos[now.i+1],INF);//cout<<"1del:"<<pos[now.i+1]<<endl; }if (flagj==-1) add=S.query_min(1,rpos[himinpos[now.i]]);else if (flagj==0) add=S.query_min(lpos[himinpos[now.i]],rpos[himaxpos[now.i]]);else add=S.query_min(lpos[himaxpos[now.i]],t_n);//For(pi,n) cout<<S.query_min(pi,pi)<<' ';cout<<" Test"<<endl;ans[now.i]=min(ans[now.i],tmp+add); if (b1){S.set(pos[now.i-1],fee_add(now.i-1,flagj,flagi));//cout<<"1add:"<<pos[now.i-1]<<endl; }if (b2){S.set(pos[now.i+1],fee_add(now.i+1,flagj,flagi));//cout<<"1add:"<<pos[now.i+1]<<endl; }}} }void work3(const int flagj) // (1,flagj){//cout<<"--------------------------\n";MEM(b)const int flagi=1; qsort(a+1,m,sizeof(node),cmp2);S.mem(t_n);Fork(i,2,t_n-1)S.set(pos[i],fee_add(i,flagj,flagi)),b[pos[i]]=1;ForD(i,m){node now=a[i];//now.print(); if (now.flag==1) {S.set(pos[now.i],INF),b[pos[now.i]]=0;//cout<<"del:"<<pos[now.i]<<endl; }else if (now.flag==0){ll tmp=fee_tmp(now.i,flagj,flagi),add;bool b1=0,b2=0;ll t1=0,t2=0;if (b[pos[now.i-1]]){b1=1;S.set(pos[now.i-1],INF);//cout<<"1del:"<<pos[now.i-1]<<endl; }if (b[pos[now.i+1]]){b2=1;S.set(pos[now.i+1],INF); //cout<<"1del:"<<pos[now.i+1]<<endl; }if (flagj==-1) add=S.query_min(1,rpos[himinpos[now.i]]);else if (flagj==0) add=S.query_min(lpos[himinpos[now.i]],rpos[himaxpos[now.i]]);else add=S.query_min(lpos[himaxpos[now.i]],t_n);//For(pi,n) cout<<S.query_min(pi,pi)<<' ';cout<<" Test"<<endl;//cout<<now.i<<' '<<flagj<<' '<<lpos[himinpos[now.i]]<<' '<<himaxpos[now.i]<<' '<<tmp<<' '<<add<<endl; ans[now.i]=min(ans[now.i],tmp+add); if (b1){S.set(pos[now.i-1],fee_add(now.i-1,flagj,flagi)); //cout<<"1add:"<<pos[now.i-1]<<endl; }if (b2){S.set(pos[now.i+1],fee_add(now.i+1,flagj,flagi));//cout<<"1add:"<<pos[now.i+1]<<endl; }}} }void solve() //无首尾,不相邻 {for(int i=-1;i<=1;i++){work1(i);work2(i);work3(i);}}int main(){//freopen("bzoj1099.in","r",stdin);//freopen("bzoj1099.out","w",stdout);scanf("%d",&n);For(i,n) scanf("%lld",&h[i]);Fork(i,2,n-1) {himax[i]=max(h[i-1],h[i+1]),himin[i]=min(h[i-1],h[i+1]),v[i]=dis(i,i-1)+dis(i,i+1);if (h[i-1]<h[i+1]) himinpos[i]=i-1,himaxpos[i]=i+1;else himinpos[i]=i+1,himaxpos[i]=i-1;}m=0;Fork(i,2,n-1){a[++m]=node(i,-1,himin[i]);a[++m]=node(i,0,h[i]);a[++m]=node(i,1,himax[i]);}//hash tablet_n=n;For(i,n) h2[i]=make_pair(h[i],i);sort(h2+1,h2+1+n);For(i,n) pos[h2[i].second]=i;//For(i,n) cout<<h2[i].first<<' '<<h2[i].second<<endl;// 区间框定 lpos[h2[1].second]=1;Fork(i,2,t_n)lpos[h2[i].second]=(h2[i].first==h2[i-1].first)?lpos[h2[i-1].second]:i;rpos[h2[t_n].second]=t_n;ForD(i,t_n-1)rpos[h2[i].second]=(h2[i].first==h2[i+1].first)?rpos[h2[i+1].second]:i;//For(i,n) cout<<lpos[i]<<' '<<rpos[i]<<' '<<pos[i]<<endl;ll res=0;For(i,n-1) res+=dis(i,i+1);if (n==2) //首尾,相邻 {printf("%lld\n%lld\n",res,res);return 0;} pre_work();solve();For(i,n) printf("%lld\n",res+ans[i]);return 0;}





0 0
原创粉丝点击