Codeforces Round 995 (Div. 3)(A~F题解)

 

不要问为什么没有G,因为G我还没搞明白,我是蒟蒻,补药降维打击窝

A. Preparing for the Olympiad 

思路:我们要让差值最大,我们发现,ai做了,那么bi+1就要做,因此我们可以去遍历整个数组,去寻找ai>bi+1的即可,然后累加起来差值就是最终结果

#include<bits/stdc++.h>
using namespace std;
#define int long long
int t;
int n;
int a[200005];
int b[200005];
string s;

void solve()
{
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		cin>>a[i];
	}
	for(int i=1;i<=n;i++)
	{
		cin>>b[i];
	}
	int ans=0;
	for(int i=1;i<=n;i++)
	{
		if(a[i]>b[i+1])
		ans+=a[i]-b[i+1];
	}
	cout<<ans<<"\n";
	for(int i=1;i<=n;i++)
	{
		a[i]=b[i]=0;
	}
}
signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cin>>t;
    while(t--)
    {
        solve();
    }
    return 0;
}

 B. Journey

思路:纯模拟的一道水题吧,先把总和求出来,看总共能走多少个三天,然后逐渐减,判断最后的结果

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

int t;  
int n;  
int a, b, c;  

void solve() {  
    cin >> n >> a >> b >> c;  
    int mod=n%(a+b+c);
    int time = n/(a+b+c)*3;
	if(mod>0)
	{
		mod-=a;
		time++;
	}
	if(mod>0)
	{
		mod-=b;
		time++;
	}
if(mod>0)
	{
		mod-=c;
		time++;
	}
    cout << time << '\n';  
}  

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

 C. Preparing for the Exam

思路:这题我们发现可以分三种情况

1.q等于n,说明所有的答案都能拿到,那么我们m份试卷都应当为1

2.q<n-1 ,说明我们至少缺了两份答案,无论做哪个试卷都是0

3q=n-1,说明我们缺了一份试卷,我们找到缺的那个试卷,当mi为缺的那个试卷的标号的时候结果就是1,否则就是0

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

int t;  
int n, m, k;  
vector<int> a(300005);  
vector<int> q(300005);  
vector<int> vis(300005);  

void solve()  
{  
    for(int i=1;i<=n;i++)
    {
    	vis[i]=0;
	}
    cin >> n >> m >> k;  
    for (int i = 1; i <= m; i++)  
    {  
        cin >> a[i];  
    }  
    
    for (int i = 1; i <= k; i++)  
    {  
        cin >> q[i];  
        vis[q[i]] = 1;  
    }  
     
    if (k >= n)  
    {  
        cout << string(m, '1') << "\n";  
        return;  
    }  
    else if (k < n - 1)  
    {  
        cout << string(m, '0') << "\n";  
        return;  
    }  
    else 
    {  
        int flag = 0;  
        for (int i = 1; i <= n; i++)  
        {  
            if (vis[i] == 0)  
            {  
                flag = i;  
                break;  
            }  
        }  
        
        for (int i = 1; i <= m; i++)  
        {  
            if (a[i] == flag)  
            {  
                cout << 1;  
            }  
            else  
            {  
                cout << 0;  
            }  
        }  
        cout << "\n";  

        return;  
    }  
}  

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

D. Counting Pairs

 思路:我们去枚举要用到的点,然后去算出另外一个点的取值范围(上界和下界)

然后去二分查找上界和下界的坐标,然用坐标之差即为可用的数字,但是我们同时要注意减去自己与自己匹配的情况,因为左右边界可能会覆盖当前这个点的值

减去之后除2即为最终结果

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

int t;  
int n, x, y;  
int a[200005];  

void solve()  
{  
    cin >> n >> x >> y;  
    int sum = 0;  
    for (int i = 0; i < n; i++)  
    {  
        cin >> a[i];  
        sum += a[i];  
    }  
    sort(a, a + n);   

    int ans = 0;   
    int tong = 0;   
    for (int i = 0; i < n; i++)  
    {  
        int L = sum - y;  
        int R = sum - x;  
        int left = lower_bound(a, a + n, L - a[i]) - a;   
        int right = upper_bound(a, a + n, R - a[i]) - a;  
        
        if(left <= i && right > i)  
        {  
            tong++;  
        }   
        ans += (right - left);   
    }  
    cout << (ans - tong) / 2 << "\n";   
}  

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

E. Best Price

思路:这题看数据就知道要离散化一下,但是呢,我们可以将其存进vector里面,这样来处理离散化的操作,我们可以对a进行排序,对b进行排序,然后将a,b的数值存进一个set里面,这样可以完成去重的操作,然后去遍历这个set里面的数值,然后去计算有多少购买的人,如果差评数小于k即可进行计算最大值

我们这里来分析一下为什么用数组中的数就可以了,因为假设数组中没有p这个值,但是p+1在这个数组中,我们完全可以用p+1来代替p,来获得更大的收益,反之亦然,假设数组中有p这个元素p的下一个元素为q,假设p+1不为q,我们完全可以用q来代替p+1,来获得更大的收益,因为购买的人数是一样的

#include <bits/stdc++.h>  
using namespace std;  
#define int long long  
int t;  
int n, k; 
void solve() 
{   
    cin >> n >> k;  
    vector<int> a(n);  
    for(int i=0;i<n;i++)
    {
    	cin>>a[i];
	}
    vector<int> b(n);  
    for(int i=0;i<n;i++)
    {
    	cin >> b[i];  
	}
    sort(a.begin(), a.end());  
    sort(b.begin(), b.end());  
    vector<int> v = a;  
    v.insert(v.end(), b.begin(), b.end());  
    sort(v.begin(), v.end());  
    v.erase(unique(v.begin(), v.end()), v.end());  
    int maxn = 0;  
    for(auto p : v) 
	{  
        int flag = n - (lower_bound(a.begin(), a.end(), p) - a.begin()); 
        int sum = n - (lower_bound(b.begin(), b.end(), p) - b.begin()); 
        int z = sum - flag; 
        if(z <= k) 
		{  
            int cnt = flag + z;  
            int ans = p * cnt;  
            maxn = max(maxn, ans); 
        }  
    }  
    cout << maxn << "\n";  
}  

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

 F. Joker

 思路:这题的思维很巧妙,在看到数据之前,一开始我想的是要搜索,就是去遍历两种选择的情况,后来一看数据直接给我劝退了,因此就要去想另一种操作了,我们并不一定就要去求出具体的值是哪个,我们可以用区间来转换这道题目

我们来分析一下三种可能的情况

假设x为我们的小丑牌,o为正常牌,我们将选择的牌标红来区别

假设我们当前的区间范围为{m,m}

1.我们选择的牌是小丑牌区间左边的牌

ooxoo

那么我们经过操作可能出现的范围为{m-1,m}

2.我们选择的小丑牌区间右边的牌

ooxoo

那么我们经过操作可得到的范围为{m,m+1}

3.我们选择的是小丑牌区间内的数 

(1)同样分两种情况,一种是小丑牌区间长度不为1

oooxxxooo 

那么我们可以分出来三个区间

{1,1},{l,r},{n,n}

(2)小丑牌区间长度为1

oooxooo 

可以分出来两个区间

{1,1},{n,n}

有可能区间会重叠,那我们就更新前面那个区间的右端点即可,这样维护更加便捷

 那么我们的思路就找到了,直接开写即可,

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define pb push_back
#define pii pair<int,int>
int n,m,q;
int flag;
void solve()
{
	cin>>n>>m>>q;
	vector<pii> p;
	p.push_back({m,m});
    for(int i=1;i<=q;i++)
	{
		cin>>flag;
		vector<pii> copy;
		for(auto u:p)
		{
			int a=u.first;
			int b=u.second;
			if(flag<a)
			{
				copy.push_back({a-1,b});
			}
			else if(b<flag)
			{
				copy.push_back({a,b+1});
			}
			else
			{
				copy.push_back({1,1});
				copy.push_back({n,n});
				if(a!=b)
				{
					copy.push_back({a,b});
				}
			}
		}
		sort(copy.begin(),copy.end());
		p.clear();
		for(auto u:copy)
		{
			int a=u.first;
			int b=u.second;
			if(p.empty()||p.back().second<a)
			{
				p.push_back({a,b});
			}
			else 
			{
				p.back().second=max(p.back().second,b);
			}
		} 
		int ans=0;
		for(auto u:p)
		{
			int a=u.first;
			int b=u.second;
			ans+=(b-a+1);
		}
		cout<<ans<<" ";
	}
	cout<<"\n";
	return;
}
signed main()
{
	int t;
	cin>>t;
	while(t--)
	solve();
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值