Codeforces Round #727 (Div. 2)

本文介绍了如何使用排序和双指针技术解决两道竞赛题目。第一题涉及学生分组,要求形成稳定的学生小组,每个小组内相邻学生的水平差不超过给定值,通过邀请额外学生来最小化小组数量。第二题是关于商品购买的优化问题,Lena需要购买多种商品,并在享受折扣的情况下花费最少的钱。通过合理安排购买顺序,可以找到最低花费。两题的解决方案都涉及到对数据的排序和利用双指针进行优化。
摘要由CSDN通过智能技术生成

C

C. Stable Groups
time limit per test1 second
memory limit per test256 megabytes
inputstandard input
outputstandard output
There are n students numerated from 1 to n. The level of the i-th student is ai. You need to split the students into stable groups. A group of students is called stable, if in the sorted array of their levels no two neighboring elements differ by more than x.

For example, if x=4, then the group with levels [1,10,8,4,4] is stable (because 4−1≤x, 4−4≤x, 8−4≤x, 10−8≤x), while the group with levels [2,10,10,7] is not stable (7−2=5>x).

Apart from the n given students, teachers can invite at most k additional students with arbitrary levels (at teachers' choice). Find the minimum number of stable groups teachers can form from all students (including the newly invited).

For example, if there are two students with levels 1 and 5; x=2; and k≥1, then you can invite a new student with level 3 and put all the students in one stable group.

Input
The first line contains three integers n, k, x (1≤n≤200000, 0≤k≤1018, 1≤x≤1018) — the initial number of students, the number of students you can additionally invite, and the maximum allowed level difference.

The second line contains n integers a1,a2,…,an (1≤ai≤1018) — the students levels.

Output
In the only line print a single integer: the minimum number of stable groups you can split the students into.

Examples
inputCopy
8 2 3
1 1 5 8 12 13 20 22
outputCopy
2
inputCopy
13 0 37
20 20 80 70 70 70 420 5 1 5 1 60 90
outputCopy
3
Note
In the first example you can invite two students with levels 2 and 11. Then you can split the students into two stable groups:

[1,1,2,5,8,11,12,13],
[20,22].
In the second example you are not allowed to invite new students, so you need 3 groups:

[1,1,5,5,20,20]
[60,70,70,70,80,90]
[420]

题解:排序后将所有差值大于x的值push到cha里,与k进行比较,若能够消除间隙,则pop掉,最后若有y个间隙,则ans=y+1。
另外要注意cha为空时答案为1(比赛时由于没考虑wa7),n==1时答案也为1。
#include<bits/stdc++.h>
#define int long long
 
using namespace std;
 
inline int read()  {  
    int x=0,f=1;  
    char ch=getchar();  
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}  
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}  
    return x*f;  
}
 
const int maxn=2e5+10;
int a[maxn];
int T;
 
bool cmp(int a,int b){
    return a>b;
}
 
void solve(){
    vector<int>cha;
    int n,k,x;
    n=read(),k=read(),x=read();
    for(int i=1;i<=n;++i) a[i]=read();
    if(n==1){
        puts("1");
        return;
    }
    if(k>=1e18-n){
        puts("1");
        return;
    }
    sort(a+1,a+n+1);
    for(int i=2;i<=n;++i){
        if(a[i]-a[i-1]>x){
            cha.push_back(a[i]-a[i-1]);
        }
    }
    if(cha.empty()){
        puts("1");
        return;
    }
    sort(cha.begin(),cha.end(),cmp);
    for(int i=cha.size()-1;i>=0;--i){
        int d=cha[i]/x;
        if(d==0) continue;
        //if(k<d) break;
        if(cha[i]%x!=0){
            if(k<d) break;
            k-=d;
            cha.pop_back();
            if(k<=0) break;
        }
        else if(cha[i]%x==0){
            if(k<d-1) break;
            k-=(d-1);
            cha.pop_back();
            if(k<=0) break;
        }
    }
    cout<<cha.size()+1<<endl;
} 
 
signed main()
{
    solve();
    //for(;;);
	return 0;
}

D

D. PriceFixed
time limit per test1 second
memory limit per test256 megabytes
inputstandard input
outputstandard output
Lena is the most economical girl in Moscow. So, when her dad asks her to buy some food for a trip to the country, she goes to the best store  — "PriceFixed". Here are some rules of that store:

The store has an infinite number of items of every product.
All products have the same price: 2 rubles per item.
For every product i there is a discount for experienced buyers: if you buy bi items of products (of any type, not necessarily type i), then for all future purchases of the i-th product there is a 50% discount (so you can buy an item of the i-th product for 1 ruble!).
Lena needs to buy n products: she must purchase at least ai items of the i-th product. Help Lena to calculate the minimum amount of money she needs to spend if she optimally chooses the order of purchasing. Note that if she wants, she can buy more items of some product than needed.

Input
The first line contains a single integer n (1≤n≤100000) — the number of products.

Each of next n lines contains a product description. Each description consists of two integers ai and bi (1≤ai≤1014, 1≤bi≤1014) — the required number of the i-th product and how many products you need to buy to get the discount on the i-th product.

The sum of all ai does not exceed 1014.

Output
Output the minimum sum that Lena needs to make all purchases.

Examples
inputCopy
3
3 4
1 3
1 5
outputCopy
8
inputCopy
5
2 7
2 8
1 2
2 4
1 8
outputCopy
12
Note
In the first example, Lena can purchase the products in the following way:

one item of product 3 for 2 rubles,
one item of product 1 for 2 rubles,
one item of product 1 for 2 rubles,
one item of product 2 for 1 ruble (she can use the discount because 3 items are already purchased),
one item of product 1 for 1 ruble (she can use the discount because 4 items are already purchased).
In total, she spends 8 rubles. It can be proved that it is impossible to spend less.

In the second example Lena can purchase the products in the following way:

one item of product 1 for 2 rubles,
two items of product 2 for 2 rubles for each,
one item of product 5 for 2 rubles,
one item of product 3 for 1 ruble,
two items of product 4 for 1 ruble for each,
one item of product 1 for 1 ruble.
In total, she spends 12 rubles.
题解:将数组以原价保底购买次数升序排列,运用双指针即可。双指针实现思路由位大佬给出。
#include<bits/stdc++.h>
#define int long long

using namespace std;

inline int read()  {  
    int x=0,f=1;  
    char ch=getchar();  
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}  
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}  
    return x*f;  
}

const int maxn=1e5+10;
int a[maxn],b[maxn];//所需数量,达到多少才有折扣
int T;

pair<int,int>ob[maxn];

bool cmp(pair<int,int>a,pair<int,int>b){
    return a.second<b.second;
}

void solve(){
    int n;
    n=read();
    for(int i=1;i<=n;++i) ob[i].first=read(),ob[i].second=read();
    sort(ob+1,ob+n+1,cmp);
    //for(int i=1;i<=n;++i) cout<<ob[i].first<<" "<<ob[i].second<<endl;
    int cost=0,buy=0;
    int pre=1,las=n;
    while(pre!=las){
        if(buy>=ob[pre].second){
            cost+=ob[pre].first;
            buy+=ob[pre].first;
            ob[pre].first=0;
        }
        else{
            int cur=min(ob[pre].second-buy,ob[las].first);
            cost+=2*cur;
            buy+=cur;
            ob[las].first-=cur;
        }
        if(ob[pre].first==0) pre++;
        if(ob[las].first==0) las--;
    }
    int cur=min(ob[pre].first,max(ob[pre].second-buy,(int)0));
    cost+=2*cur;
    cost+=ob[pre].first-cur;
    cout<<cost<<endl;
}

signed main()
{
    solve();
    //for(;;);
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值