輸出原序列有45分……ios
字典序最小能夠和拓撲序聯繫起來。ide
根據原來的題意不是很可作,因而對原序列求逆,令q[p[i]]=i;優化
那麼就成功將題意轉化:相鄰元素值的差大於等於k時能夠交換,使序列字典序最小。ui
考慮一下$n^2$怎麼作,對於$i<j$,若是$abs(q[i]-q[j])<k$,那麼q[i]和q[i]的大小關係不會發生變化,那麼連一條$q[i]->q[j]$的邊表示q[i]在q[j]以前,跑拓撲排序就能夠了。spa
考慮優化,其實作過不少這種題了(‘炸彈’),圖中會存在$A->B,B->C,A->C$之類的邊,顯然$A->C$能夠去掉。怎麼實現呢?對於一個q[i],是向右邊差小於k的連邊,那麼其實只須要連兩條邊,即離他最近的大於他的和小於他的,那麼其它的點也會被他們限制。code
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #include<cmath> 5 #include<queue> 6 #define LL long long 7 using namespace std; 8 struct edge 9 { 10 int u,v,nxt; 11 #define u(x) ed[x].u 12 #define v(x) ed[x].v 13 #define n(x) ed[x].nxt 14 }ed[10000010]; 15 int first[500010],num_e; 16 #define f(x) first[x] 17 int n,k,p[500010],q[500010],du[500010]; 18 struct TREE 19 { 20 struct tree 21 { 22 int l,r,ls,rs,minn; 23 #define l(x) tr[x].l 24 #define r(x) tr[x].r 25 #define ls(x) tr[x].ls 26 #define rs(x) tr[x].rs 27 #define minn(x) tr[x].minn 28 }tr[10000000]; 29 int cnt,root; 30 void build(int &x,int l,int r) 31 { 32 if(!x)x=++cnt; 33 l(x)=l,r(x)=r,minn(x)=0x7fffffff; 34 if(l==r)return; 35 int mid=(l+r)>>1; 36 build(ls(x),l,mid); 37 build(rs(x),mid+1,r); 38 } 39 void add(int x,int pos,int y) 40 { 41 // cout<<x<<" "<<l(x)<<" "<<r(x)<<" "<<pos<<" "<<y<<endl; 42 if(l(x)==r(x)){minn(x)=y;return;} 43 int mid=(l(x)+r(x))>>1; 44 if(pos<=mid)add(ls(x),pos,y); 45 else add(rs(x),pos,y); 46 minn(x)=min(minn(ls(x)),minn(rs(x))); 47 } 48 int ask(int x,int l,int r) 49 { 50 if(l(x)>=l&&r(x)<=r)return minn(x); 51 int mid=(l(x)+r(x))>>1,ans=0x7fffffff; 52 if(l<=mid)ans=min(ans,ask(ls(x),l,r)); 53 if(r> mid)ans=min(ans,ask(rs(x),l,r)); 54 return ans; 55 } 56 }T; 57 inline void add(int u,int v); 58 signed main() 59 { 60 cin>>n>>k;T.build(T.root,1,n); 61 for(int i=1;i<=n;i++) 62 cin>>p[i],q[p[i]]=i; 63 64 // for(int i=1;i<=n;i++)cout<<q[i]<<" ";puts(""); 65 for(int i=n;i;--i) 66 { 67 int t1=T.ask(1,max(1,q[i]-k+1),min(n,q[i]-1)), 68 t2=T.ask(1,max(1,q[i]+1),min(n,q[i]+k-1)); 69 // cout<<i<<" "<<t1<<" "<<t2<<" "<<q[i]<<endl; 70 if(t1!=0x7fffffff)add(q[i],q[t1]),du[q[t1]]++; 71 if(t2!=0x7fffffff)add(q[i],q[t2]),du[q[t2]]++; 72 T.add(1,q[i],i); 73 } 74 75 priority_queue<int,vector<int>,greater<int> >que; 76 for(int i=1;i<=n;i++)if(!du[i])que.push(i); 77 int cnt=0; 78 while(!que.empty()) 79 { 80 int x=que.top();q[++cnt]=x;que.pop(); 81 for(int i=f(x);i;i=n(i)) 82 { 83 du[v(i)]--; 84 if(!du[v(i)])que.push(v(i)); 85 } 86 } 87 for(int i=1;i<=n;i++)p[q[i]]=i; 88 89 for(int i=1;i<=n;i++)cout<<p[i]<<endl; 90 } 91 inline void add(int u,int v) 92 { 93 // cout<<"add: "<<u<<" "<<v<<endl; 94 ++num_e; 95 u(num_e)=u; 96 v(num_e)=v; 97 n(num_e)=f(u); 98 f(u)=num_e; 99 }
%%mikufun權值線段樹優化建邊。blog