在z[]单调不减时,中位数贪心,用可合并堆维护区间。
在z[]单调递增时,T[i]=t[i]-i,用上述方法处理。相当于此时求得的z[]虽然单调不减,但在恢复为t时,一定单调递增。
http://www.lydsy.com/JudgeOnline/problem.php?id=1367
/************************************************************** Problem: 1367 User: 1349367067 Language: C++ Result: Accepted Time:7092 ms Memory:28616 kb ****************************************************************/ #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; int n; struct Node { int x,dis,size; Node *l,*r; void clear() { l=r=NULL; dis=0;size=1; } }a[1000011]; bool check_dis(Node *A) { if (A->r==NULL) return false; if (A->l==NULL) return true; return (A->r->dis>A->l->dis); } Node *merge(Node *A,Node *B) { if (A==NULL) return B; if (B==NULL) return A; if (A->x<B->x) swap(A,B); A->r=merge(A->r,B); if (check_dis(A)) swap(A->l,A->r); if (A->r==NULL) A->dis=0; else A->dis=A->r->dis+1; A->size=1; if (A->l!=NULL) A->size+=A->l->size; if (A->r!=NULL) A->size+=A->r->size; return A; } Node *Q[1000011]; int Qs[1000011]; int num=0; void fix(int i,int n) { //cout<<n<<"**"<<endl; //system("pause"); while (Q[i]->size>(n+1)/2) { //cout<<Q[i]->size<<endl; //system("pause"); Q[i]=merge(Q[i]->l,Q[i]->r); } } inline int abs(int x) {return x<0?(-x):x;} void init() { for (int i=1;i<=n;i++) { a[i].clear(); scanf("%d",&a[i].x); a[i].x-=i; } num=1;Q[1]=&a[1];Qs[0]=0;Qs[1]=1; for (int i=2;i<=n;i++) { num++; Q[num]=&a[i];Qs[num]=i; while (num>1&&Q[num]->x<Q[num-1]->x) { Q[num-1]=merge(Q[num],Q[num-1]); //cout<<num<<" "<<Qs[num]<<" "<<Qs[num-1]<<endl; Qs[num-1]=Qs[num];num--; //cout<<num<<"OO"<<endl; fix(num,Qs[num]-Qs[num-1]); //system("pause"); } } long long ans=0ll; for (int i=1;i<=num;i++) { for (int j=Qs[i-1]+1;j<=Qs[i];j++) { ans+=abs(a[j].x-Q[i]->x); } } //cout<<"*"<<num<<endl; //for (int i=1;i<=num;i++) // cout<<Qs[i]<<"*"<<(Q[i]->x)<<" "; //cout<<endl; printf("%lld\n",ans); } int main() { scanf("%d",&n); init(); return 0; }