题目链接:HDU 5338
题意:给一个去掉括号的置换半成品,问如何加括号可以使原序列字典序最大。
思路:
思路很明确
- 1、肯定是贪心的考虑使靠前位置的尽量大。
- 2、那么就找从当前位置到之前的右括号之间最大的值与后继进行比较。
- 括号直接用SET维护就可以了,最大值用线段树维护。比赛的时候SB用线段树维护的右括号位置,幸亏范围小。
代码:
#include <cstdio>
#include <cstring>
#include <queue>
#include <iostream>
#include <algorithm>
#define Lson o<<1,l,mid
#define Rson o<<1|1,mid+1,r
#define MID int mid = (l+r)>>1
using namespace std;
const int maxn=100100;
int data[maxn],fd[maxn];
//namespace SGM1{
// set<int> st;
// int init(int n){
// st.clear();
// st.insert(0);
// }
// int get(int pos){
// return 0-*st.lower_bound(-pos);
// }
// int update(int pos){
// st.insert(-pos);
// }
//}
namespace SGM1{
int maxv[maxn*4];
int maxe=-1,n;
void init(int _n){
n=_n;
for(int i=0;i<4*maxn;i++){
maxv[i]=0;
}
}
void modify(int o,int l,int r,int pos){
if(l==r){
maxv[o]=pos;
return ;
}
MID;
if(pos<=mid)modify(Lson,pos);
else modify(Rson,pos);
maxv[o]=max(maxv[o<<1],maxv[o<<1|1]);
}
void quarry(int o,int l,int r,int L,int R){
if(L<=l&&r<=R){
maxe=max(maxe,maxv[o]);
return ;
}
MID;
if(L<=mid)quarry(Lson,L,R);
if(R>mid )quarry(Rson,L,R);
}
int get(int pos){
maxe=-1;
quarry(1,1,n,1,pos);
return maxe;
}
int update(int pos){
modify(1,1,n,pos);
}
}
namespace SGM2{
int maxv[maxn*4];
int maxe,n;
int a[maxn];
int maxa(int x,int y){
if(a[x]>a[y]) return x;
return y;
}
void build(int o,int l,int r){
if(l==r){
maxv[o]=l;
return ;
}
MID;
build(Lson);
build(Rson);
maxv[o]=maxa(maxv[o<<1],maxv[o<<1|1]);
}
void init(int _n){
n=_n;
a[0]=0;
for(int i=1;i<=n;i++)a[i]=data[i];
build(1,1,n);
}
void modify(int o,int l,int r,int pos){
if(l==r){
maxv[o]=l;
return ;
}
MID;
if(pos<=mid)modify(Lson,pos);
else modify(Rson,pos);
maxv[o]=maxa(maxv[o<<1],maxv[o<<1|1]);
}
void quarry(int o,int l,int r,int L,int R){
if(L<=l&&r<=R){
maxe=maxa(maxe,maxv[o]);
return ;
}
MID;
if(L<=mid)quarry(Lson,L,R);
if(R>mid )quarry(Rson,L,R);
}
int get(int L,int R){
maxe=0;
quarry(1,1,n,L,R);
return maxe;
}
void update(int pos){
a[pos]=0;
modify(1,1,n,pos);
}
}
int ans[maxn];
int main(){
int n,T;
// freopen("data.txt","r",stdin);
scanf("%d",&T);
while(T--){
memset(ans,0,sizeof(ans));
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&data[i]);
fd[data[i]]=i;
}
SGM1::init(n);
SGM2::init(n);
for(int i=1;i<=n;i++){
if(!ans[i]){
int tpos=SGM1::get(fd[i])+1;
tpos=SGM2::get(tpos,fd[i]);
if(data[tpos]>data[fd[i]+1]||SGM1::get(fd[i]+1)>=fd[i]+1||fd[i]==n){
SGM1::update(tpos);
SGM1::update(fd[i]);
for(int j=tpos;j<fd[i];j++){
ans[data[j]]=data[j+1];
}
ans[i]=data[tpos];
}
else{
SGM2::update(fd[i]+1);
ans[i]=data[fd[i]+1];
}
}
}
for(int i=1;i<=n;i++){
if(i>1)putchar(' ');
printf("%d",ans[i]);
}
puts("");
}
return 0;
}