洛谷P3165 [CQOI2014]排序機械臂
阿新 • • 發佈:2017-11-26
urn spa stdin open point 排序 fread 機械臂 static
題目描述
為了把工廠中高低不等的物品按從低到高排好序,工程師發明了一種排序機械臂。它遵循一個簡單的排序規則,第一次操作找到攝低的物品的位置P1,並把左起第一個至P1間的物品反序;第二次找到第二低的物品的位置P2,並把左起第二個至P2間的物品反序...最終所有的物品都會被排好序。
上圖給出_個示例,第_次操作前,菝低的物品在位置4,於是把第1至4的物品反序;第二次操作前,第二低的物品在位罝6,於是把第2至6的物品反序...
你的任務便是編寫一個程序,確定一個操作序列,即每次操作前第i低的物品所在位置Pi,以便機械臂工作。需要註意的是,如果有高度相同的物品,必須保證排序後它們的相對位置關系與初始時相同。
輸入輸出格式
輸入格式:
第一行包含正整數n,表示需要排序的物品數星。
第二行包含n個空格分隔的整數ai,表示每個物品的高度。
輸出格式:
輸出一行包含n個空格分隔的整數Pi。
輸入輸出樣例
輸入樣例#1: 復制
6
3 4 5 1 6 2
輸出樣例#1: 復制
4 6 4 5 6 6
好變態的題啊。
我們可以發現一個很顯然的規律:
第\(i-1\)小的數一定不可能在第\(i\)次查詢的區間裏
那麽我們可以維護一下最小值,對於每次詢問,在區間內找到最小值
然後打上標記就好
#include<iostream> #include<cstdio> #include<algorithm> using namespace std; const int MAXN=1e5+10; const int maxn=0x7fffff; const int INF=0x7fffffff; #define ls tree[x].ch[0] #define rs tree[x].ch[1] inline char nc() { static char buf[MAXN],*p1=buf,*p2=buf; return p1==p2&&(p2=(p1=buf)+fread(buf,1,MAXN,stdin),p1==p2)?EOF:*p1++; } inline int read() { char c=nc();int x=0,f=1; while(c<'0'||c>'9'){c=nc();} while(c>='0'&&c<='9'){x=x*10+c-'0';c=nc();} return x*f; } int n,m; struct Q { int val,pos; }a[MAXN]; struct node { int tot,fa,ch[2],mn,mnpos,v; bool rev; }tree[MAXN]; int tot,point; int root; int PosL,PosR; inline void connect(int x,int fa,bool how) { tree[x].fa=fa; tree[fa].ch[how]=x; } inline void update(int k) { if(!k) return ; tree[k].tot=tree[tree[k].ch[0]].tot+tree[tree[k].ch[1]].tot+1; tree[k].mn=tree[k].v; tree[k].mnpos=k; if(tree[k].ch[0]&&tree[tree[k].ch[0]].mn<tree[k].mn) tree[k].mn=tree[tree[k].ch[0]].mn,tree[k].mnpos=tree[tree[k].ch[0]].mnpos; if(tree[k].ch[1]&&tree[tree[k].ch[1]].mn<tree[k].mn) tree[k].mn=tree[tree[k].ch[1]].mn,tree[k].mnpos=tree[tree[k].ch[1]].mnpos; } inline int BuildTree(int l,int r) { if(l>r) return 0; int mid=(l+r)>>1; if(l!=r) { connect(BuildTree(l,mid-1),mid,0); connect(BuildTree(mid+1,r),mid,1); } tree[mid].rev=0; tree[mid].mn=a[mid].val; tree[mid].v=a[mid].val; tree[mid].mnpos=mid; update(mid); return mid; } inline bool ident(int x) { return tree[tree[x].fa].ch[1]==x; } inline void pushdown(int x) { if(tree[x].rev) { swap(tree[x].ch[0],tree[x].ch[1]); tree[tree[x].ch[0]].rev^=1; tree[tree[x].ch[1]].rev^=1; tree[x].rev=0; } } inline void rotate(int X) { pushdown(tree[X].fa);pushdown(X); int Y=tree[X].fa; if(Y==root) root=X; int R=tree[Y].fa; bool Yson=ident(X); bool Rson=ident(Y); int B=tree[X].ch[Yson^1]; connect(B,Y,Yson); connect(Y,X,Yson^1); connect(X,R,Rson); update(Y);update(X); } inline void splay(int x,int to) { to=tree[to].fa; while(tree[x].fa!=to) { if(tree[tree[x].fa].fa==to) rotate(x); else if(ident(x)==ident(tree[x].fa)) rotate(tree[x].fa),rotate(x); else rotate(x),rotate(x); } update(x); } int find(int x, int rk) { pushdown(x);//標記下傳 if(tree[ls].tot+1==rk) return x; else if(tree[ls].tot >= rk) return find(ls, rk); else return find(rs, rk-tree[ls].tot-1); } const int comp(const Q a,const Q b) { return a.val<b.val||(a.val==b.val&&a.pos<b.pos); } const int comp2(const Q a,const Q b) { return a.pos<b.pos; } int QueryMin(int l,int r) { int x1=find(root,l); int x2=find(root,r+2); splay(x1,root); splay(x2,tree[x1].ch[1]); return tree[ tree[x2].ch[0] ].mnpos; } inline void rever(int l,int r) { int x1=find(root,l),x2=find(root,r+2); splay(x1,root);splay(x2,tree[x1].ch[1]); tree[tree[x2].ch[0]].rev^=1; } int main() { #ifdef WIN32 freopen("a.in","r",stdin); #else #endif int n=read(); a[1].val=a[n+2].val=INF; for(int i=2;i<=n+1;i++) a[i].val=read(),a[i].pos=i; sort(a+2,a+n+2,comp); for(int i=2;i<=n+1;i++) a[i].val=i-1; sort(a+2,a+n+2,comp2); //for(int i=1;i<=n+2;i++) printf("%d ",a[i].pos);printf("\n"); BuildTree(1,n+2); root=(n+3)>>1; for(int i=1;i<=n;i++) { int x=QueryMin(i,n); splay(x,root); int out=tree[tree[x].ch[0]].tot; rever(i,out); printf("%d ",out); } }
洛谷P3165 [CQOI2014]排序機械臂