Codeforces Round #622 (Div. 2)(B(思维),C2(单调栈))

题目链接

B. Different Rules

题意:现有n个人参加两轮的比赛,每次比赛每个人都有一个排名,最终的排名就是两次排名的和,数字小的在前面,

注意:不会出现两次比赛都一样的情况

做法:排名靠前的简单,就是x+y-1,注意排名不要超过n(被这个点wa两发),  排名靠后呢?

假设 这个人 两次排名 是x,y

那么就是使得尽量多的人排名<=x+y 那就是 两列两种情况取其中一种即可

(x-1 y+1)        (x+1 ,y-1)

(x-2 y+2)        (x+2 ,y-2)

(x-3 y+3)        (x+3 ,y-3)

....                  .....

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=(b);++i)
#define mem(a,x) memset(a,x,sizeof(a))
#define pb push_back
#define pi pair<int, int>
#define mk make_pair
using namespace std;
typedef long long ll;
ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}
int a[5];
int main()
{
    int _;cin>>_;while(_--)
    {
 
        int n,x,y;
        cin>>n>>x>>y;
        if(x>y) swap(x,y);
        int ans=0;
        int t=max(0,n-y-1);//y后面有多少个可以给x的前面 
        int mi=min(x-1,t);//取个最小值 
        int t1=x-1-mi;
 
        t=max(0,n-x-1);//x后面有多少个可以给y前面 
        mi=min(y-1,t);//取个最小值 
        int t2=y-1-mi;
 
        mi=max(t1,t2);//两种情况取个最大值 
 
 
        int ans2=min(n,x-1+y);//注意不要超过n 
        mi=min(mi+1,n);
        printf("%d %d\n",mi,ans2);
    }
}

C2. Skyscrapers (hard version)

题意:给你n个建筑最高能修 的高度,现在你要构造一个凸字形的建筑,问如何分布高度 使得总高度最大。

做法:单调栈  正着一遍  反着一遍就可以了  

扫描二维码关注公众号,回复: 10150435 查看本文章

正着:pre[i]前i个保持递增序列的最大前缀和

反着:last[i]    后i个保持递减序列的最大后缀和

然后O(n)枚举下 找到和最大的那个点即可。

注意还需要并查集维护下当前下标i 影响的最左边的那个下标位置,例如  5 6 2  那么pre[3]  3这个下标就会影响至1  变成2 2 2 使得pre[3]=6

那么此时 1 2 3 就变成一样的点了。

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=(b);++i)
#define mem(a,x) memset(a,x,sizeof(a))
#define pb push_back
#define pi pair<int, int>
#define mk make_pair
using namespace std;
typedef long long ll;
ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}
const int N=5e5+10;
ll a[N],n,ans[N],pre[N],last[N],len[N],l1[N];
int fa[N];
int main()
{
    cin>>n;
    for(int i=1;i<=n;++i){
        scanf("%lld",&a[i]);
        len[i]=1;
        l1[i]=1;
        fa[i]=i;
    }
 
 
    stack<int>sta;
    sta.push(1);
    pre[1]=a[1];
 
 
    for(int i=2;i<=n;++i){
        if(sta.size()&&a[i]>=a[sta.top()]) sta.push(i),pre[i]=pre[i-1]+a[i];
        else{
            int id=i;
            while(sta.size()&&a[i]<a[sta.top()]) l1[i]+=l1[sta.top()],id=fa[sta.top()],sta.pop();
            sta.push(i);
            fa[i]=id;
            pre[i]=l1[i]*a[i]+pre[id-1];
        }
    }
 
    last[n]=a[n];
    while(sta.size()) sta.pop();
    sta.push(n);
    rep(i,1,n) fa[i]=i;
    for(int i=n-1;i;--i){
        if(sta.size()&&a[i]>=a[sta.top()]) sta.push(i),last[i]=last[i+1]+a[i];
        else{
            int id=i;
            while(sta.size()&&a[i]<a[sta.top()]) id=fa[sta.top()],len[i]+=len[sta.top()],sta.pop();
            sta.push(i);
            fa[i]=id;
//            if(i==5){
//                printf("i:%d len[i]:%lld id:%d\n",i,len[i],id);
//            }
            last[i]=a[i]*len[i]+last[id+1];
        }
    }
    ll sum=0,id=0;
 
    for(int i=1;i<=n;++i){
        if(pre[i-1]+last[i]>sum){
            sum=pre[i-1]+last[i];
            id=i;
        }
    }
    //rep(i,1,n) printf("i:%d pre:%lld\n",i,pre[i]);
    //for(int i=n;i;--i) printf("i:%d las:%lld\n",i,last[i]);
 
    //printf("id:%d\n",id);
 
    //printf("pre:%lld last:%lld\n",pre[4],last[5]);
 
    ans[id]=a[id];
    for(int i=id-1;i>=1;--i){
        ans[i]=min(ans[i+1],a[i]);
    }
    for(int i=id+1;i<=n;++i){
        ans[i]=min(ans[i-1],a[i]);
    }
    rep(i,1,n) printf("%lld ",ans[i]);
}
 
/*
7
7 2 5 6 7 6 5
 
7
7 6 5 2 5 6 7
ans:33
*/
发布了498 篇原创文章 · 获赞 66 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/qq_41286356/article/details/104481758
今日推荐