Codeforces 900C - Remove Extra One(思维好题)

Remove Extra One
time limit per test2 seconds
memory limit per test256 megabytes
inputstandard input
outputstandard output

You are given a permutation p p of length n. Remove one element from permutation to make the number of records the maximum possible.
We remind that in a sequence of numbers a1,a2,...,ak a 1 ,   a 2 ,   . . . ,   a k the element ai a i is a record if for every integer j(1j<i) j ( 1   ≤   j   <   i ) the following holds: aj<ai a j   <   a i .

input
The first line contains the only integer n(1n105) n ( 1   ≤   n   ≤   10 5 ) — the length of the permutation.
The second line contains n n integers p1,p2,...,pn (1pin) ( 1   ≤   p i   ≤   n ) — the permutation. All the integers are distinct.

Output
Print the only integer — the element that should be removed to make the number of records the maximum possible. If there are multiple such elements, print the smallest one.

Examples
Input
1
1
Output
1
Input
5
5 1 2 3 4
Output
5

Note
In the first example the only element can be removed.

解题思路

先给一波官方题解:

In this problem you have to find an element after which removal the number of records is maximum possible.
Let ri be an array consisting of 0 and 1 depending on whether the ith i − t h element was a record initially or not. We can compute it easily in O(N) O ( N ) .
Let xi x i be the difference between the number of records after removal the i-th element and initial number of records.
Let’s think of how does removal of ai influence the array ri r i . First of all, ri r i becomes 0. rj(j<i) r j ( j   <   i ) do not change in this case. Some of rj(j>i) r j ( j   >   i ) , change from 0 to 1. These elements are not records initially, but become records after the removal. These elements are elements which have only one greater element in front of them — ai a i .
Here follows an O(n2) O ( n 2 ) solution. Let’s fix ai a i — the element we are going to remove. Let xi=ri x i =   −   r i  +  the number of such j j that j>i, ai>aj a i   >   a j , and for all k(ki,k<j) k ( k   ≠   i ,   k   <   j ) ak<aj. a k   <   a j . We can compute this just looping through all j j and keeping the maximum over all elements but the ith.
Now note that it’s not required to fix ai a i . rj r j can become 1 from 0 only when a certain element from the left is removed. Let’s loop through all aj a j and determine if there is an element to the left such that it is greater than aj a j , but all other elements are less than aj a j . We can check this using ordered set. If there is such a ai a i , then increase xi x i by 1. After the loop the array xi x i is fully computed, so we can just find the element which brings the maximum number of records, and minimum among such.

一个元素比它前面的所有元素都大,称此元素为 record r e c o r d

首先用一个标记数组 r[i] r [ i ] 表示第i个元素是(1)否(0)是 record r e c o r d ,在 O(N) O ( N ) 时间内可以求出。

然后考虑移除一个元素 i i 后,能影响哪些record

自身。还有:在他之后的,某些原本不是 record r e c o r d 的,因为 i i 的移除,成为record的。

这些 record r e c o r d (称为 j j )有这样的特点:比从1到j1 i i 外的元素都大,但不比i大。

记从1到 j1 j − 1 i i 外的元素的最大值为k,则可表示为 k<j<=i k < j <= i 。此不等式为本题“题眼”。

这样就有了官方的 O(N2) O ( N 2 ) 解法:枚举要移除的元素 i i ->检查i及在他之后的 j j ,计算record增量->得移除后能使 record r e c o r d 最大的元素。

然而BB半天, 1e5 1 e 5 数据,显然超时。

这时候想想“题眼”,那个神奇的不等式。

同样设(删除 j j 后的)增量数组x[j] O(N) O ( N ) 顺推并维护 k k i不就可以了?

如果 j>i j > i ,说明 j j record x[j] x [ j ] − − ,并更新 j j i k k i

如果 k<j=<i k < j =< i ,“题眼”, x[i]++ x [ i ] + + (注意是 i i ),并更新k j j

最后的问题,如果存在相同的元素,映射不唯一,一首凉凉?

回头审题,distinct,计划通,代码非常简单。

小坑点,第一个元素是不算 record r e c o r d 的。

AC代码

#include<bits/stdc++.h>
using namespace std;

int a[100050];

int main()
{
    int n;
    while(cin>>n){
        memset(a,0,sizeof(a));
        int x,m2nd=0,m1st=0;
        for(int i=1;i<=n;i++){
            cin>>x;
            if(x>m1st){
                m2nd=m1st;
                m1st=x;
                a[x]--;
            }
            else if(x>m2nd){
                m2nd=x;
                a[m1st]++;
            }
        }
        int ma=-0x3f3f3f3f,mi;
        for(int i=1;i<=n;i++)
            if(a[i]>ma)
                ma=a[i],mi=i;
        printf("%d\n",mi);
    }
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值