因为起名无能,所以数组意义弄混了,一直wr,终于过了,结论就是好好学英语,养成自己起名的一贯习惯。这道题的重点在于怎么找有效区间内最大的值,通过看别的代码(http://blog.csdn.net/winddreams/article/details/47156293),才发现原来可以这样写。好多天了,终于把这道题过了,披着组合数学外衣的线段树!!!!!!
(今天中午吃的砂锅麻花,再一次感叹,学校的砂锅,即使夏天吃,也很好吃,想吃木桶豆腐和羊肉泡馍。)
2015.8.29:
对于数的大小比较和字典序的大小比较似乎都会有一个贪心的过程。
(如果有人在说,学数学有什么意义的话,我就可以正大光明的告诉它,可以在csdn的博客里写文章,每次的验证码都让我感觉回到了小学,每天30道计算题)
#include<stdio.h>
#include<string.h>
#include<iostream>
using namespace std;
#define N 100010
struct node{
int maxnum;
int maxb;
};
struct node array[4*N];
int num[N];
int loca[N];
int ans[N];
int sign[N];
int a,b;
int max(int a,int b){
return a>b?a:b;
}
void update(int root){
array[root].maxnum=max(array[root<<1].maxnum,array[(root<<1)+1].maxnum);
array[root].maxb=max(array[root<<1].maxb,array[(root<<1)+1].maxb);
return;
}
void build(int root,int l,int r){
if(l==r){
scanf("%d",&num[l]);
array[root].maxnum=num[l];
array[root].maxb=0;
loca[num[l]]=l;
return;
}
else{
int middle=(l+r)>>1;
build(root<<1,l,middle);
build((root<<1)+1,middle+1,r);
update(root);
return;
}
}
int queryb(int root,int l,int r){
//printf("%d %dha %d %dhei ",l,r,a,b);
if(a>b){
return -1;
}
else{
if(a<=l&&b>=r){
return array[root].maxb;
}
else{
int middle=(l+r)>>1;
if(b<=middle){
return queryb(root<<1,l,middle);
}
else if(a>middle){
return queryb((root<<1)+1,middle+1,r);
}
else{
return max(queryb(root<<1,l,middle),queryb((root<<1)+1,middle+1,r));
}
}
}
}
int querynum(int root,int l,int r){
if(l==r){
return array[root].maxnum;
}
else{
int middle=(l+r)>>1;
if(a<=l&&b>=r){
return array[root].maxnum;
}
else{
if(b<=middle){
return querynum(root<<1,l,middle);
}
else if(a>middle){
return querynum((root<<1)+1,middle+1,r);
}
else{
return max(querynum(root<<1,l,middle),querynum((root<<1)+1,middle+1,r));
}
}
}
}
void updateb(int root,int l,int r){
if(l==r){
array[root].maxb=l;
return;
}
else{
int middle=(l+r)>>1;
if(a<=middle){
updateb(root<<1,l,middle);
}
else{
updateb((root<<1)+1,middle+1,r);
}
update(root);
return;
}
}
void updatenum(int root,int l,int r){
if(l==r){
array[root].maxnum=-1;
return;
}
else{
int middle=(l+r)>>1;
if(a<=middle){
updatenum(root<<1,l,middle);
}
else{
updatenum((root<<1)+1,middle+1,r);
}
update(root);
return;
}
}
int main(){
int t;
int n;
scanf("%d",&t);
while(t--){
scanf("%d",&n);
if(n==0){
continue;
}
memset(array,0,sizeof(array));
build(1,1,n);
memset(ans,-1,sizeof(ans));
memset(sign,0,sizeof(sign));
for(int i=1;i<=n;i++){
if(ans[i]!=-1){
continue;
}
else{
int k1,k2,k3;
a=1;
b=loca[i]-1;
int templ=queryb(1,1,n);//printf("wo shi da hao ren");
templ++;
if(templ==0||templ==loca[i]){
k1=-1;
}
else{
a=templ;
b=loca[i]-1;
k1=querynum(1,1,n);
}//k1的值已验证正确
if((loca[i]-1>=1)&&ans[num[loca[i]-1]]==i){
k2=-1;
}
else{
k2=i;
}
/*if(i==4){
printf("%d %d\n",ans[loca[i]+1],ans[5]);
}*/
if((loca[i]+1<=n)&&(ans[num[loca[i]+1]]==-1)){
k3=num[loca[i]+1];
}
else if((loca[i]+1<=n)&&num[loca[i]+1]<i&&ans[num[loca[i]+1]]!=num[loca[i]+1]&&sign[num[loca[i]+1]]==0){
k3=num[loca[i]+1];
}
else{
k3=-1;
}
if(k1>k2&&k1>k3){
sign[k1]=1;
for(int j=loca[k1];j<loca[i];j++){
ans[num[j]]=num[j+1];
}
ans[i]=k1;
a=loca[i];
updateb(1,1,n);
}
else if(k2>k1&&k2>k3){
sign[k2]=1;
ans[i]=k2;
a=loca[i];
updateb(1,1,n);
}
else if(k3>k1&&k3>k2){
ans[i]=k3;
a=loca[k3];
updatenum(1,1,n);
}
//printf("%d %d %d %d\n",i,k1,k2,k3);
}
}
printf("%d",ans[1]);
for(int i=2;i<=n;i++){
printf(" %d",ans[i]);
}
printf("\n");
}
return 0;
}