2 6 1 4 5 6 3 2 2 1 2
4 6 2 5 1 3 2 1
题目:
很复杂。不想说
:解法
贪心,从1到n确定该位置能放的最大的数
对于每个位置,只能是后一个数作为自己的后继,或者,在这个位置之前没有被用过的数才能作为后继。
但是:必须从前面没有匹配括号的地方去找最大值
比如
5 4 1 3 2
找1的时候发现了5那么(5,4,1)就是一个循环了。找2的时候只能从3的位置开始
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; #define maxm 400007 #define maxn 100011 int tree[maxn]; int Tquery(int p){ int ans = 0; while(p > 0){ if(ans < tree[p]) ans = tree[p]; p -= (p&(-p)); } return ans; } int flag; int Tadd(int p,int x){ while(p < flag){ if(tree[p] < x) tree[p] = x; p += (p&(-p)); } return 0; } int lc[maxm],rc[maxm],val[maxm]; int cnt ; void init(){ cnt = 1; lc[0] = rc[0] = val[0] = 0; } int num[maxm]; int pos[maxm]; void update(int u){ val[u] = max(val[lc[u]],val[rc[u]]); } void build(int u,int l,int r){ lc[u] = rc[u] = val[u] = 0; if(l == r){ val[u] = num[l]; return ; } lc[u] = cnt++; rc[u] = cnt++; int mid = (l+r)/2; build(lc[u],l,mid); build(rc[u],mid+1,r); update(u); } //查询区间最大值 int query(int u,int l,int r,int L,int R){ if(val[u] == 0) return 0; if(l == L && r == R) return val[u]; int mid = (l+r)/2; if(mid >= R) return query(lc[u],l,mid,L,R); else if(mid < L) return query(rc[u],mid+1,r,L,R); return max(query(lc[u],l,mid,L,mid),query(rc[u],mid+1,r,mid+1,R)); } //将一个结点置为0 void del(int u,int l,int r,int p){ if(l == r){ val[u] = 0; return ; } int mid = (l+r)/2; if(p > mid) del(rc[u],mid+1,r,p); else del(lc[u],l,mid,p); update(u); } //删除一个区间的结点,置为0 void delx(int u,int l,int r,int L,int R){ if(l == L && r == R) { val[u] = 0; return ; } int mid = (l+r)/2; if(mid >= R) delx(lc[u],l,mid,L,R); else if(mid < L) delx(rc[u],mid+1,r,L,R); else delx(lc[u],l,mid,L,mid),delx(rc[u],mid+1,r,mid+1,R); } int ans[maxn]; int check[maxn]; int ok[maxn]; int main(){ int t,n; scanf("%d",&t); while(t--){ scanf("%d",&n); num[0] = 0; for(int i = 1;i <= n;i++) { scanf("%d",&num[i]); pos[num[i]] = i; } flag = n+10; init(); cnt++; build(1,0,n); if(n > 1000){ memset(check,0,sizeof(check)); memset(ok,0,sizeof(ok)); memset(tree,0,sizeof(tree)); } else { for(int i = 0;i <= flag; i++) tree[i] = check[i] = ok[i] = 0; } int u,v; for(int i = 1;i <= n; i++){ if(ok[i]) continue; ok[i] = 1; int p = pos[i]; if(p != n && check[p+1] == 0) u = num[p+1]; else u = 0; int be = Tquery(p); int v = query(1,0,n,be+1,p); if(u > v){ ans[i] = u; check[p+1] = 1; del(1,0,n,p+1); } else if(v > 0){ ans[i] = v; check[p] = 1; int q = pos[v]; for(int j = q; j < p; j++){ if(!ok[num[j]]){ ok[num[j]] = 1; ans[num[j]] = num[j+1]; } check[j] = 1; } delx(1,0,n,q,p); Tadd(q,p); } } for(int i = 1;i <= n; i++){ if(i!=1)printf(" %d",ans[i]); else printf("%d",ans[i]); } printf("\n"); } return 0; } /* 4 4 3 4 2 1 */