Codeforces Round #703 (Div. 2)(A-C)

本文详细介绍了三个算法问题的解决方案:如何通过移动操作使堆栈高度严格递增,如何找到使得所有房屋到展览馆距离之和最小的点,以及如何在不超过20次查询中找到数组中最大值的位置。每个问题都给出了思路和C++代码实现,涉及数据结构、最优化和交互式查询等算法概念。
摘要由CSDN通过智能技术生成

题目链接

A. Shifting Stacks

您有n叠积木,第i个堆栈包含hi块,其高度是其中的积木块数。一次移动可以从第i个堆栈中取出一个积木(如果至少有一个)并将其放入第i + 1个堆栈中。您可以使堆栈高度严格递增吗?
注意:堆栈数始终为n,即使堆栈中积木数量为0也不会消失。

思路

我们在构造的过程中使堆栈以0,1,2……n-1的数量排列,只要在过程中检验是否可以达成即可。

代码

#include<bits/stdc++.h>
using namespace std;
const int mod=1e9+7;
const int maxn=1e6+5;
typedef long long ll;
const int inf=1e9;
ll sum,a[maxn];
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    int t;
    cin>>t;
    while(t--)
    {
        sum=0;
        int n;
        cin>>n;
        bool flag=0;
        for(int i=1;i<=n;i++)
        {
            cin>>a[i];
            sum+=(a[i]-i+1);
            if(sum<0)
                flag=1;
        }
        if(!flag)
            cout<<"YES"<<endl;
        else
            cout<<"NO"<<endl;
    }
    return 0;
}

B. Eastern Exhibition

您和您的朋友住在n所房屋中,每个房屋都位于2D平面的整数坐标点上,同一地点可能有不同的房屋。市长要求您为建造东方展览馆寻找地方,您必须找到使从所有房屋到展览馆的总距离最小的位置的数量(带有整数坐标的点)。展览馆可以建在与房屋相同的地方,两点(x1,y1)和(x2,y2)之间的距离是| x1-x2 | + | y1-y2 |,其中| x |是x的绝对值。

思路

本题实际为中位数的二维推广,一维状态下若数量为奇数,则展览馆位置唯一(第(n+1)/2个数)。若为偶数,则可以在第n/2与第n/2+1之间任意选取,二维状态下只需要将符合条件的矩阵面积求出即可。
注意:端点是可以选取的

代码

#include<bits/stdc++.h>
using namespace std;
const int mod=1e9+7;
const int maxn=1e6+5;
typedef long long ll;
const int inf=1e9;
ll x[maxn],y[maxn];
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    int t;
    cin>>t;
    while(t--)
    {
        int n;
        cin>>n;
        for(int i=1;i<=n;i++)
            cin>>x[i]>>y[i];
        if(n%2)
            cout<<"1"<<endl;
        else
        {
            sort(x+1,x+1+n);
            sort(y+1,y+1+n);
            cout<<(x[n/2+1]-x[n/2]+1)*(y[n/2+1]-y[n/2]+1)<<endl;
        }
    }
    return 0;
}

C. Guessing the Greatest

有一个由n个不同数字组成的数组,在一次查询中,您可以询问子段a [l…r]中区间第二大值所在的位置。在不超过20个查询中找到数组中最大值的位置,子段a [l…r]是al,al + 1,…,ar中的所有值。询问此子段后,您将获得整个数组中该子段第二大值的位置。

思路

之前比赛里接触过二分交互题,本题与之类似,对于1e5的数据量,log的复杂度显然是符合要求的。由于每次问询获得的结果为区间的第二大值的位置,所以我们可以将整个区间中第二大值的位置ans作为二分的依据。如果在ans为端点的某段区间内,区间第二大值的位置不等于ans,则说明最大值不在此区间中。所以在获得ans后即可初步确定区间最大值所在的区间范围,然后根据mid与ans所组成的区间的区间第二大值位置是否等于ans来确定最大值位于哪一区间。

代码

#include<bits/stdc++.h>
using namespace std;
const int mod=1e9+7;
const int maxn=1e6+5;
typedef long long ll;
const int inf=1e9;
int ans,tmp;
int ask(int l,int r)
{
    if(l==r)
        return -1;//l==r的区间是不符合条件的,不可以进行问询
    cout<<"? "<<l<<" "<<r<<endl;
    int res;
    cin>>res;
    return res;
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    int n;
    cin>>n;
    int l,r;
    ans=ask(1,n);
    if(ask(ans,n)==ans)
    {
        l=ans,r=n;//最大值在ans右边的区间内
        while(l<=r)
        {
            int mid=(l+r)/2;
            if(ask(ans,mid)==ans)
                r=mid-1;
            else
                l=mid+1;//不明白的可以画图
        }
        cout<<"! "<<l<<endl;
    }
    else
    {
        l=1,r=ans;
        while(l<=r)
        {
            int mid=(l+r)/2;
            if(ask(mid,ans)==ans)
                l=mid+1;
            else
                r=mid-1;
        }
        cout<<"! "<<r<<endl;
    }
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值