2023ICPC杭州区域赛

The 2023 ICPC Asia Hangzhou Regional Contest (The 2nd Universal Cup. Stage 22: Hangzhou)

M.V-Diagram

题意:

V图:长度>=3,且包含一个最小值,最小值前面的数降序排列,最小值后面的数升序排列。

给定一个V图a,找出在V图a中平均值最大的V图b。

思路:

找到V图中的最小值标记下标为b,此时从b点动态规划会发现:

从b点开始,左边的数均比b大,加上后平均值一定比当前的数大,但是此时如果向右边规划,不能保证加上右边的数平均数一定会增大,因为无法保证右边的数比当前的平均数大。

因此可以将V图的平均数大的区域分为三部分:

1 1~b+1

2 b-1~n

3 1~n

无法保证哪边平均值,因此取得三个范围的平均数进行比较取最大即可

Solved

const int N=3e5+10;
int a[N];
void solve()
{
    int n;cin>>n;
    double sum=0,sum1=0,sum2=0;
    int mi=INT_MAX,b;
    for(int i=1;i<=n;i++){
        cin>>a[i];
        sum+=a[i];//存所有范围值
        if(a[i]<mi){
            mi=a[i];
            b=i;//记录最小值下标
        }
    }
    for(int i=1;i<=b+1;i++){//存左段范围值,保证是V图
        sum1+=a[i];
    }
    for(int i=b-1;i<=n;i++){//存右段范围值,保证是V图
        sum2+=a[i];
    }
    //加上一段绝对值比较优,加上另一段不清楚,因此三个范围全计算出进行比较
    double x=sum/n;//两段均加
    double y=sum1/(b+1);//加左段不加右段
    double z=sum2/(n-(b-1)+1);//加右段不加左段
    double ans=max(x,max(y,z));
    printf("%.20lf\n",ans);
}

D. Operator Precedence

题意:

给定n,构造出长度2n的序列满足:

1 a1* a2+a3* a4+a5* a6+…+a2n-1* a2n

2 a1* (a2+a3)* (a2+a4)* (a5+a6) …*a2n

保证1,2式子值相同

思路:

通过分析成分,2中 中间两数先加后全乘的递增程度要比1中 两两想乘在想加的递增程度大的

因此可以令2中的( ai +( ai+1) ) 为1,再构造a1,a2n,所以令ai=-1,ai+1=2;

此时

1 a1* (-1)+(-2)+(-2)+…+2* a2n

2 a1* a2n

令a1=1,解出a2n=2n-3

Solved

void solve()
{
    int n;cin>>n;
    cout<<"1 ";
    int q=n-1;
    while(q--){
        cout<<"-1 2 ";
    }
    cout<<2*n-3<<endl;
}

J.Mysterious Tree

题意:

交互题 每次询问答案由输出给出。换行符用endl可不清空缓冲区,若用’\n’应使用cout.flush();清除缓冲区

给出n个节点,确定n个节点的连接方式

菊:当且仅当存在一个节点u,使得其他所有节点v都与u有节点。

链:当且仅当存在一个排序使得i 有pi->pi+1, p1,p2…pn称为链。

思路:

链中每个节点最多有两条边,而菊 中心节点大于等于三条边相连,因此只需找到任意一条连接的边,再找出两个不同于此边上的节点,判断此边上的节点(若是菊,则有一个一定是中心节点)是否可以与这两个不同的点连接,如果中心节点可以和这两个节点相连,则是菊,否则是链。

Solved

参考学长代码

const int N=1e5+10;
int a[N];
int n;
int ask(int u,int v)
{
    cout<<"? "<<u<<" "<<v<<endl;//询问问题
    int x;cin>>x;
    return x;//给出答案
}
int check(int u,int v)
{
    int k=0;
    for(int i=1;i<=n;i++){
        if(i!=u&&i!=v)//确定两个不同于u,v的点
        a[k++]=i;//存入数组中使用
        if(k==2) break;
    }
    int sum=0;
    if(ask(u,a[0])==1){//如果u与a[0]相连,则判断u是否与a[1]相连,相连则菊,不想连则链
        sum=1+ask(u,a[1]);
    }else{//如果u与a[0]不相连,则判断v是否与a[1],a[2]相连
        sum=ask(v,a[0])+ask(v,a[1]);
    }
    if(sum==2) return 2;
    else return 1;//如果sum值为0,是链,在链中v可既不与a[0]又不与a[1]连
}
void solve()
{  
    cin>>n;
    int res=-1;
    for(int i=1;i<=n;i+=2){
        if(ask(i,i%n+1)==1){//只需找到一条相连接的边即可
            res=check(i,i%n+1);//再找两个不同的点判断
            break;
        }
    }
    if(res==-1) cout<<"! 1"<<endl;
    else cout<<"! "<<res<<endl;
}

模板:

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


void solve()
{
    
}
signed main()
{
    std::ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    int n;cin>>n;
    while(n--){
        solve();
    }
    return 0;
}
  • 20
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值