Codeforces Round 961 (Div. 2) A B1 B2 C

A. Diagonals

题目

给 Vitaly503 一个方格棋盘,棋盘的一边有 n n n 和 k k k 个筹码。他意识到所有这些 k k k 芯片都需要放置在棋盘的单元格上(一个单元格上不能放置超过一个芯片)。

让我们把第 i i i 行和第 j j j 列中的单元格表示为 ( i , j ) (i ,j) (i,j) 。对角线是指 i + j i + j i+j 值相同的单元格集合。例如,单元格 ( 3 , 1 ) (3, 1) (3,1) 、 ( 2 , 2 ) (2, 2) (2,2) 和 ( 1 , 3 ) (1, 3) (1,3) 位于同一条对角线上,但 ( 1 , 2 ) (1, 2) (1,2) 和 ( 2 , 3 ) (2, 3) (2,3) 不在同一条对角线上。如果一条对角线上至少包含一个棋子,那么这条对角线就被称为 "被占 "对角线。

请计算在所有放置 k k k 的筹码中,被占对角线的最少数目。

输入

每个测试由多组输入数据组成。第一行包含一个整数 t t t ( 1 ≤ t ≤ 500 1 \le t \le 500 1≤t≤500 ) - 输入数据集的数量。然后是各组输入数据的说明。

每组输入数据的唯一一行包含两个整数 n n n , k k k ( 1 ≤ n ≤ 100 , 0 ≤ k ≤ n 2 1 \le n \le 100, 0 \le k \le n^2 1≤n≤100,0≤k≤n2 )( 1 ≤ n ≤ 100 , 0 ≤ k ≤ n 2 1 \le n \le 100, 0 \le k \le n^2 1≤n≤100,0≤k≤n2 ) - 分别是棋盘的边数和可用筹码数。

输出

对于每组输入数据,输出一个整数--在放置所有 k k k 个筹码后,他能得到的至少有一个筹码的对角线的最小占位数。

解题思路

cpp 复制代码
![如图](https://i-blog.csdnimg.cn/direct/dd61373bc85e4a2c8624a490402059bc.jpeg#pic_center)


画图可得
有 1 条长度为 n 的对角线,有 2 条长度为 (1~n-1) 的对角线

AC代码

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define fi first
#define se second
#define PII pair<int,int>
#define ALL(x) x.begin(),x.end()
const int N=2e5+10;
void solve()
{
    int ans=0;
    int n,k;cin>>n>>k;
    if(k==0)
    {
    	cout<<"0\n";
    	return;
	}
    for(int i=n;i>=1;i--)
    {
        if(i==n)
        {
            ans++;
            k-=n;
            continue;
        }
        if(k<=0)break;
        ans++;
        k-=i;
        if(k<=0)break;
        ans++;
        k-=i;
    } 
    cout<<ans<<'\n';
}

signed main()
{
	ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    int t;
    cin>>t;
    while(t--)solve();
    return 0;
}

B1. Bouquet (Easy Version)

题目

这是问题的简单版本。唯一不同的是,在这个版本中,花朵是通过枚举来指定的

一个女孩准备过生日,想买一束最漂亮的花。商店里一共有 n n n 种花,每种花的特征是花瓣数,一朵有 k k k 个花瓣的花需要花费 k k k 枚硬币。女孩决定,花束中任何两朵花的花瓣数之差都不能超过 1。同时,女孩希望花束的花瓣数尽可能多。不幸的是,她只有 m m m 枚金币,不能再花更多的钱。她能组合的花束的花瓣总数最多是多少?
输入

每个测试由多个测试用例组成。第一行包含一个整数 t t t ( 1 ≤ t ≤ 10   000 1 \le t \le 10\,000 1≤t≤10000 ) - 测试用例数。随后是测试用例的说明。

每个测试用例的第一行包含两个整数 n n n , m m m ( 1 ≤ n ≤ 2 ⋅ 1 0 5 , 1 ≤ m ≤ 1 0 18 1 \le n \le 2 \cdot 10^5, 1 \le m \le 10^{18} 1≤n≤2⋅105,1≤m≤1018 ) --分别是商店里的鲜花数量和女孩拥有的硬币数量。每个测试用例的第二行包含 n n n 个整数 a 1 , a 2 , ... , a n a_1, a_2, \ldots, a_n a1,a2,...,an ( 1 ≤ a i ≤ 1 0 9 1 \le a_i \le 10^9 1≤ai≤109 ),其中 a i a_i ai 是商店里第 i i i 朵花的花瓣数。

所有测试用例的 n n n 之和不超过 2 ⋅ 10 5 2 \cdot {10}^5 2⋅105 。
输出

对于每个测试用例,输出一个整数,即在满足上述所有条件的情况下,女孩在花束中可能组合的最大花瓣数。

解题思路

cpp 复制代码
用队列维护先后顺序,不符合题意就出队

AC代码

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=2e5+10;
int a[N];
void solve()
{
    int n,m;cin>>n>>m;
    memset(a,0,sizeof(a));
    int sum=0,ma=0;
    queue<int>q;
    for(int i=0;i<n;i++)
        cin>>a[i];
    sort(a,a+n);
    for(int i=0;i<n;i++)
    {
        q.push(a[i]); // 入队
        sum+=a[i]; // 累加
        while(!q.empty()&&a[i]>(q.front()+1)) // 大于 1个 花瓣数出队
        {
            sum-=q.front();
            q.pop();
        }
        while(!q.empty()&&sum>m) // 总和大于 m ,出队
        {
        	sum-=q.front();
        	q.pop();
		}
        if(sum<=m)
            ma=max(ma,sum); // 每次变化,求最大值
    }
    cout<<ma<<'\n';
}

signed main()
{
	ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    int t;
    cin>>t;
    while(t--)solve();
    return 0;
}

B2. Bouquet (Hard Version)

题目

**这是问题的困难版本。唯一不同的是,在这个版本中,不是列出每种花的花瓣数,而是为所有类型的花设置花瓣数和商店中的花的数量。

一个女孩准备过生日,想买一束最漂亮的花。店里一共有 n n n 种不同类型的花,每种花都有花瓣数和数量。花瓣数为 k k k 的花朵售价为 k k k 枚金币。女孩决定,她用来装饰蛋糕的任何两朵花的花瓣数之差都不能超过 1。同时,女孩还想用尽可能多的花瓣组合成一束花。不幸的是,她只有 m m m 枚金币,无法再花费更多。她能组合的花束花瓣总数最多是多少?
输入

每个测试由多个测试用例组成。第一行包含一个整数 t t t ( 1 ≤ t ≤ 10   000 1 \le t \le 10\,000 1≤t≤10000 ) - 测试用例数。随后是测试用例的说明。

每个测试用例的第一行包含两个整数 n n n , m m m ( 1 ≤ n ≤ 2 ⋅ 1 0 5 , 1 ≤ m ≤ 1 0 18 1 \le n \le 2 \cdot 10^5, 1 \le m \le 10^{18} 1≤n≤2⋅105,1≤m≤1018 )--分别是商店中鲜花的种类数和女孩拥有的硬币数。每个测试用例的第二行包含 n n n 不同 的整数 a 1 , a 2 , ... , a n a_1, a_2, \ldots, a_n a1,a2,...,an ( 1 ≤ a i ≤ 1 0 9 1 \le a_i \le 10^9 1≤ai≤109 ),其中 a i a_i ai 是商店中 i i i /th 鲜花类型的花瓣数(对于不同索引 i ≠ j i \neq j i=j ,必须是 a i ≠ a j a_i \neq a_j ai=aj )。每个测试用例的第三行包含 n n n 个整数 c 1 , c 2 , ... , c n c_1, c_2, \ldots, c_n c1,c2,...,cn ( 1 ≤ c i ≤ 1 0 9 1 \le c_i \le 10^9 1≤ci≤109 ),其中 c i c_i ci 是商店中 i i i -th 种花的数量。

所有测试用例中 n n n 的总和不超过 2 ⋅ 10 5 2 \cdot {10}^5 2⋅105 。
输出

对于每个测试用例,打印一个整数 - 在遵守上述所有条件的情况下,女孩在花束中可能收集到的最大花瓣数。

解题思路

cpp 复制代码
由任何两朵花的花瓣数之差都不能超过 1 得,维护在遵守上述所有条件的情况下,只有一种花,或者有两种花瓣数差 1 的花
让花瓣数多的花数量达到合理的最多

AC代码

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define PII pair<int,int>
#define fi first
#define se second
#define ALL(x) x.begin(),x.end()

void solve()
{
    int n,m;cin>>n>>m;
    vector<PII >q(n);
    for(int i=0;i<n;i++)    cin>>q[i].fi;
    for(int i=0;i<n;i++)    cin>>q[i].se;
    int ans=0;
    sort(ALL(q));
    ans=min(m/q[0].fi,q[0].se)*q[0].fi;
    for(int i=1;i<n;i++)
    {
        if(q[i].fi-q[i-1].fi==1) // 满足差为 1
        {
            int num1=min(m/q[i-1].fi,q[i-1].se); //初使花瓣少的最多
            int num2=min((m-q[i-1].fi*num1)/q[i].fi,q[i].se);
            int re=m-num2*q[i].fi-num1*q[i-1].fi;
            int r=min(re,min(num1,q[i].se-num2)); // 花瓣数少 转化成 花瓣数多
            ans=max(ans,q[i].fi*(r+num2)+q[i-1].fi*(num1-r));
        }
        else // 不满足差为 1
            ans=max(ans,min(q[i].se,m/q[i].fi)*q[i].fi);
    }
    cout<<ans<<'\n';
}

signed main()
{
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    int t;cin>>t;
    while(t--)solve();
    return 0;
}

C. Squaring

题目

ikrpprpp 发现了一个由整数组成的数组 a a a 。他喜欢公正,所以想让 a a a 变得公平,也就是让它不递减。为此,他可以在数组的索引 1 ≤ i ≤ n 1 \le i \le n 1≤i≤n 上执行一次公正行动,将 a i a_i ai 替换为 a i 2 a_i ^ 2 ai2 (位置 i i i 的元素与其平方)。例如,如果 a = [ 2 , 4 , 3 , 3 , 5 , 3 ] a = [2,4,3,3,5,3] a=[2,4,3,3,5,3] 和ikrpprpp选择对 i = 4 i = 4 i=4 执行正义行动,那么 a a a 就会变成 [ 2 , 4 , 3 , 9 , 5 , 3 ] [2,4,3,9,5,3] [2,4,3,9,5,3] 。

要使数组不递减,最少需要多少次正义行动?
输入

第一行包含一个整数 t t t ( 1 ≤ t ≤ 1000 1 \le t \le 1000 1≤t≤1000 )。( 1 ≤ t ≤ 1000 1 \le t \le 1000 1≤t≤1000 )--测试用例的数量。随后是测试用例说明。

对于每个测试用例,第一行包含一个整数 n n n - 数组的大小 a a a 。- 数组的大小 a a a 。第二行包含 n n n ( 1 ≤ n ≤ 2 ⋅ 1 0 5 1 \le n \le 2 \cdot 10 ^5 1≤n≤2⋅105 ) 个整数 a 1 , a 2 , ... , a n a_1, a_2,\ldots, a_n a1,a2,...,an ( 1 ≤ a i ≤ 1 0 6 1 \le a_i \le 10 ^ 6 1≤ai≤106 )。

所有测试用例中 n n n 的总和不超过 2 ⋅ 10 5 2 \cdot {10}^5 2⋅105 。
输出

对于每个测试用例,打印一个整数--使数组 a a a 不递减所需的最小正义行为数。如果无法做到,则打印 − 1 -1 −1 。

解题思路

cpp 复制代码
每一位继承前一位的平方次数,x<y,x 与 y 同时平方相同次数大小关系不变

AC代码

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define int long long
#define fi first
#define se second
#define PII pair<int,int>
#define ALL(x) x.begin(),x.end()
void solve()
{
    int n;cin>>n;
    vector<int >a(n+1);
    vector<int >b(n+1);
    for(int i=1;i<=n;i++)    cin>>a[i];
    for(int i=2;i<=n;i++)
    {
        if(a[i]==a[i-1]) // 与上一位相同时,直接继承上一位的平方次数
        {
            b[i]=b[i-1];
            continue;
        }
        if(a[i]==1)	// 特判,因为 1 的平方 等于 1
        {
            if(a[i-1]==1)   continue; // 前一位为 1 合理
            else	// 前一位不为 1 ,不合理
            {
                cout<<"-1"<<'\n';
                return;
            }
        }
        if(a[i]>a[i-1])	// 符合升序条件,加上上一位的平方次数,减去上一位达到 x<y 的关系
        {
            if(a[i-1]==1)continue;
            int x=a[i],y=a[i-1];
            int tt=0;
            while(y<=x)
            {
                y=y*y;
                tt++;
            }
            b[i]=max(0ll,b[i-1]-tt+1); // 加上 1 达到 维护初始a[i-1]<a[i]
        }
        else	// 不符合升序条件,达到 a[i-1]<a[i] ,并继承上一位的平方次数
        {
            int x=a[i],y=a[i-1];
            int tt=0;
            while(x<y)
            {
                x=x*x;
                tt++;
            }
            b[i]=b[i-1]+tt;
        }
    }
    int ans=0;
    for(int i=1;i<=n;i++)   ans+=b[i]; // 累加各个平方次数
    cout<<ans<<'\n';
}

signed main()
{
    IOS
    int t;
    cin>>t;
    while(t--)solve();
    return 0;
}
相关推荐
van叶~15 分钟前
算法妙妙屋-------1.递归的深邃回响:二叉树的奇妙剪枝
c++·算法
knighthood200125 分钟前
解决:ros进行gazebo仿真,rviz没有显示传感器数据
c++·ubuntu·ros
半盏茶香1 小时前
【C语言】分支和循环详解(下)猜数字游戏
c语言·开发语言·c++·算法·游戏
小堇不是码农1 小时前
在VScode中配置C_C++环境
c语言·c++·vscode
Jack黄从零学c++1 小时前
C++ 的异常处理详解
c++·经验分享
捕鲸叉7 小时前
创建线程时传递参数给线程
开发语言·c++·算法
A charmer7 小时前
【C++】vector 类深度解析:探索动态数组的奥秘
开发语言·c++·算法
Peter_chq7 小时前
【操作系统】基于环形队列的生产消费模型
linux·c语言·开发语言·c++·后端
青花瓷8 小时前
C++__XCode工程中Debug版本库向Release版本库的切换
c++·xcode
幺零九零零9 小时前
【C++】socket套接字编程
linux·服务器·网络·c++