首页 > 其他分享 >Codeforces Round #852 (Div. 2)

Codeforces Round #852 (Div. 2)

时间:2023-02-12 19:46:53浏览次数:38  
标签:maxx 852 int 元素 Codeforces while Div empty define

A. Yet Another Promotion

题意:买土豆,一种卖a元一公斤,买m公斤送一公斤;一种卖b元一公斤。求买n公斤土豆最少花多少钱。

解:完全没有思考,把a*n, b*n, 买尽可能多m倍数的土豆剩下的都买a和都买b,四种情况堆上去取min。

B. Fedya and Array

题意:令一序列相邻两个元素之差为1(一头一尾也算相邻),如果一个数大于它左右两边,称其为局部最大;小于两边则为最小。现给出所有局部最大之和为x,局部最小之和为y,求任意满足要求的最短序列。

解:画一画大概是一个折线图,观察一下发现所有局部最大之和与局部最大个数没啥关系,再观察一下样例,序列长度为最大最小值相差距离的两倍。那么构造一个序列,其最小值为y,最大值为x,然后两边连起来即可。例如:x=2, y=-1,序列可以是-1, 0, 1, 2, 1, 0.

C. Dora and Search

题意:给出一个排列,求其一个子数组,使得子数组两端都不是该子数组最大值,也不是该子数组最小值。

解:试图枚举每个元素作为左端点,寻找右端点。预处理出每个元素右起第一个大于/小于它的元素位置,这个过程可以用单调栈解决。假设第一个大于它的位置为n,第一个小于它的位置为m,那么我们只能取位置大于等于max(m, n)的元素,才能使得当前元素不是最值。现在考虑判断右端点是否会为最值,同样地预处理出每个元素向左第一个大于/小于它的数的位置,看当前元素是否在这个范围外。乍一看好像是O(n2)的,但介于这是一个排列,如果当前元素是n,每次至少从n+1开始找右端点,所以最多O(nlnn)。最后用stack写的单调栈也跑得飞快,谢谢cf(

代码:

#include <bits/stdc++.h>
using namespace std;
#define maxx 200005
#define maxn 25
#define maxm 205
#define ll long long
#define inf 1000000009
#define mod 2520
int a[maxx]={0};
int biggerleft[maxx]={0};
int biggerright[maxx]={0};
int smallerleft[maxx]={0};
int smallerright[maxx]={0};
stack<int> s;
signed main(){
    int T;
    scanf("%d",&T);
    while(T--) {
        int n;
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i]);
        }
        while (!s.empty()) s.pop();
        for(int i=1;i<=n;i++){
            while(!s.empty() && a[s.top()] >= a[i]) s.pop();
            if(!s.empty()) smallerleft[i]=s.top();
            else smallerleft[i]=-1;
            s.push(i);
        }
        while (!s.empty()) s.pop();
        for(int i=1;i<=n;i++){
            while(!s.empty() && a[s.top()] <= a[i]) s.pop();
            if(!s.empty()) biggerleft[i]=s.top();
            else biggerleft[i]=-1;
            s.push(i);
        }
        while (!s.empty()) s.pop();
        for(int i=n;i>=1;i--){
            while(!s.empty() && a[s.top()] >= a[i]) s.pop();
            if(!s.empty()) smallerright[i]=s.top();
            else smallerright[i]=-1;
            s.push(i);
        }
        while (!s.empty()) s.pop();
        for(int i=n;i>=1;i--){
            while(!s.empty() && a[s.top()] <= a[i]) s.pop();
            if(!s.empty()) biggerright[i]=s.top();
            else biggerright[i]=-1;
            s.push(i);
        }
        int flag=0;
        for(int i=1;i<=n;i++){
            if(smallerright[i]==-1||biggerright[i]==-1) continue;
            int r=max(smallerright[i],biggerright[i]);
            for(int j=r;j<=n;j++){
                if(smallerleft[j]==-1||biggerleft[j]==-1) continue;
                int l=min(smallerleft[j],biggerleft[j]);
                if(i<=l){
                    printf("%d %d\n",i,j);
                    flag=1;
                    break;
                }
            }
            if(flag) break;
        }
        if(!flag) printf("-1\n");
    }
    return 0;
}
View Code

D没啥思路,明天补补

标签:maxx,852,int,元素,Codeforces,while,Div,empty,define
From: https://www.cnblogs.com/capterlliar/p/17114525.html

相关文章