题干:

We define an element aia_iai​ in a sequence "good", if and only if there exists a j(1≤j<i)j(1\le j < i)j(1≤j<i) such that aj<aia_j < a_iaj​<ai​.
Given a permutation ppp of integers from 111 to nnn. Remove an element from the permutation such that the number of "good" elements is maximized.

Input

The input consists of several test cases. The first line of the input gives the number of test cases, T(1≤T≤103)T(1\le T\le 10^3)T(1≤T≤103).
For each test case, the first line contains an integer n(1≤n≤106)n(1\le n\le 10^6)n(1≤n≤106), representing the length of the given permutation.
The second line contains nnn integers p1,p2,⋯,pn(1≤pi≤n)p_1,p_2,\cdots,p_n(1\le p_i\le n)p1​,p2​,⋯,pn​(1≤pi​≤n), representing  the given permutation ppp.
It’s guaranteed that ∑n≤2×107\sum n\le 2\times 10^7∑n≤2×107.

Output

For each test case, output one integer in a single line, representing the element that should be deleted. If there are several answers, output the minimal one.
 

Sample Input

2
1
1
5
5 1 2 3 4

Sample Output

1
5

题目大意:

定义a[i]是good,当且仅当数组中他前面的数中 存在比他小的数。给定一个n个数的序列a,保证是1~n的一个排列,现在让你删掉其中一个数(且必须删掉一个),使得good数最多。问你删掉哪个数?如果有多种可能性就输出最小的解。

解题报告:

   这题在重现赛nlogn是可以过的,但是现场赛应该是严格保证线性才能过(因为nlogn那就是个水题了啊怎么可能过的队伍这么少)。保证线性也不难,因为你会发现你只需要记录前缀最小值和次小值然后维护一下就行了。

AC代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<cctype>
using namespace std;
typedef long long ll;
const int maxn=2e7+5;
int n,m;
int val[maxn],suf[maxn]; //suf[val[i]]记录依附于val[i]的数的个数 
//cnt[i]求每个数前小于它的数的个数, minn[]同时记录前缀1~i的最小值 
int minn[maxn],cnt[maxn];
bool is[maxn];//is[i]记录val[i]是否不是前缀1~i的最小值 
inline int lowbit(int t){return t&-t;}
void add(int p,int val,int op)
{
	if(op==0){
		for(;p<=n;p+=lowbit(p))
			cnt[p]+=val;
	}
	else {
		for(;p<=n;p+=lowbit(p))
			minn[p]=min(minn[p],val);
	}
}
int query(int p,int op)
{
	int res;
	if(op){
		for(res=1e9;p;p-=lowbit(p))
			res=min(minn[p],res);
	}
	else {
		for(res=0;p;p-=lowbit(p))
			res+=cnt[p];
	}
	return res;
}
int main()
{
	int t,q,i,j,k;
	int ans,maxx,tmp,num,sum,Min;
	cin>>t;
	for(;t;t--){
		sum=0; maxx=-1; ans=1e9;
		scanf("%d",&n);
		for(i=1;i<=n;i++){
			scanf("%d",val+i);
			cnt[i]=suf[i]=is[i]=0; minn[i]=1e9;
		}
		for(i=1;i<=n;i++){
			num=query(val[i]-1,0);
			if(num){
				sum++; is[i]=1;
				if(num==1){
					tmp=query(val[i]-1,1);
					suf[tmp]++;
				}
			}
			add(val[i],1,0); add(val[i],val[i],1);
		}
		for(i=1;i<=n;i++){
			tmp=sum-(int)is[i]-suf[val[i]];
			if(tmp>maxx||tmp==maxx&&val[i]<ans) 
				{maxx=tmp; ans=val[i];}
		}
		printf("%d\n",ans);
	}
	return 0;
}
/*
7
1
1
5
5 1 2 3 4
5
4 3 5 2 1  
5
1 3 2 4 5  

1
5
1
2
*/

线性AC代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<cctype>
using namespace std;
typedef long long ll;
const int maxn=1e6+5;
int n,m1,m2;
int val[maxn],suf[maxn]; //suf[i]记录依附于val[i]的数的个数 
//cnt[i]求每个数前小于它的数的个数, minn[]同时记录前缀1~i的最小值 
bool is[maxn];//is[i]记录val[i]是否不是前缀1~i的最小值 
int main()
{
	int t,q,i,j,k;
	int ans,maxx,tmp,num,sum;
	cin>>t;
	for(;t;t--){
		sum=0; maxx=-1; ans=m1=m2=1e9;
		scanf("%d",&n);
		for(i=1;i<=n;i++){
			scanf("%d",val+i);
			suf[i]=is[i]=0; 
		}
		for(i=1;i<=n;i++){
			if(m1<val[i]){
				sum++; is[i]=1;
				if(m2>val[i]) {
					suf[m1]++; 
					m2=val[i];
				}
			}
			else {
				m2=m1; m1=val[i];
			}
		}
		for(i=1;i<=n;i++){
			tmp=sum-(int)is[i]-suf[val[i]];
			if(tmp>maxx||tmp==maxx&&val[i]<ans) 
				{maxx=tmp; ans=val[i];}
		}
		printf("%d\n",ans);
	}
	return 0;
}