Codeforces Round 980 (Div. 2)

Codeforces Round 980 (Div. 2) 总结

A

简单小学算数题。

  • 如果 \(b \le a\),直接输出 \(a\)
  • 否则,列方程 \(a-x=b-2x\)\(x=b-a\),输出 \(a-x\),即 \(2a-b\)
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
#include <map>

using namespace std;
typedef long long ll;
const int N=1;
int a,b;
void solve()
{
    cin>>a>>b;
    if(a>=b) cout<<a<<'\n';
    else cout<<max(2*a-b,0)<<'\n';
}
int main ()
{
    #ifndef ONLINE_JUDGE
    freopen("1.in","r",stdin);
    freopen("1.out","w",stdout);
    #endif 
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    int T;
    cin>>T;
    while(T--) solve();
    return 0;
}

B

这道题似乎卡了不少人 qwq。首先,因为每次不知道是不是有一个按钮按完后不出饮料,额外的贡献就产生在这,但是同一个不出的按钮又只会按一次(又不是傻子)。
所以不妨将 \(a\) 排序,从小到大取,每次先把空的按一遍,当然第一轮不计。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
#include <map>

using namespace std;
typedef long long ll;
const int N=2e5+5;
int n;
ll k,ans;
ll a[N];
void solve()
{
    cin>>n>>k;
    for(int i=1;i<=n;i++) cin>>a[i];
    sort(a+1,a+n+1);
    ans=0;
    for(int i=1;i<=n;i++)
    {
        ll t=(a[i]-a[i-1])*(n-i+1);
        ans++;
        if(k<=t)
        {
            ans+=k;
            break;
        }
        else 
        {
            k-=t;   
            ans+=t;
        }
    }
    cout<<ans-1<<'\n';
}
int main ()
{
    #ifndef ONLINE_JUDGE
    freopen("1.in","r",stdin);
    freopen("1.out","w",stdout);
    #endif 
    int T;
    cin>>T;
    while(T--) solve();
    return 0;
}


C

其实题意就是设计一种 pair 的排序。
严格证明还是要分类讨论:设数对中的最大值为 \(mx\),最小值为 \(mi\),对于两个数对 \(x,y\)

  • \(x_{mi} \le y_{mi} , x_{mx} \le y_{mx}\),显然 \(x\) 应该在前面。
  • \(x_{mi} \le y_{mi} , y_{mx} \le x_{mx}\),分析一下可知谁前谁后都一样,看作一个整体,也不会影响其他的数对的排序。

因此只需要按最小值为第一关键字,最大值为第二关键字(当然反一下也可以)排序即可。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
#include <map>

using namespace std;
typedef long long ll;
const int N=1e5+5;
struct node 
{
    int x,y;
    int mi,mx;
    friend bool operator < (const node &a,const node &b)
    {
        if(a.mx==b.mx) return a.mi<b.mi;
        else return a.mx<b.mx;
    }
}a[N];

int n;
void solve()
{
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        int x,y;
        cin>>x>>y;
        a[i].x=x,a[i].y=y;
        a[i].mi=min(x,y),a[i].mx=max(x,y);
    }
    sort(a+1,a+n+1);
    for(int i=1;i<=n;i++) cout<<a[i].x<<' '<<a[i].y<<' ';
    cout<<'\n';
}
int main ()
{
    #ifndef ONLINE_JUDGE
    freopen("1.in","r",stdin);
    freopen("1.out","w",stdout);
    #endif 
    int T;
    cin>>T;
    while(T--) solve();
    return 0;
}

D

比较巧妙的思路。

首先肯定是要尽可能地跳到下标更大的位置,然后再拿前面能拿的所有分。但是因为 \(b\) 的存在这不太好直接实现。
考虑建图,跳的过程有两种情况:

  • 不跳过,从 \(i\)\(i-1\),没有亏损。
  • 跳过,从 \(i\) 跳到 \(b_i\),要亏损 \(a_i\)的分数。

这样的话跑一遍最短路,枚举一下终点 \(i\)\(ans=pre_i-dis_i\)

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
#include <map>
using namespace std;
typedef long long ll;

typedef pair<ll,int> PLI;
const int N=4e5+5,M=N*2;
int n;
ll a[N],b[N];

int e[M],w[M],ne[M],h[N],tot;
void add(int x,int y,int z)
{
    e[++tot]=y,w[tot]=z,ne[tot]=h[x],h[x]=tot;
}
bool vis[N];
ll dis[N];
priority_queue<PLI> q;
void dijkstra()
{
    for(int i=1;i<=n;i++) vis[i]=0,dis[i]=1e18;
    dis[1]=0;
    q.push({0,1});
    while(q.size())
    {
        int x=q.top().second;q.pop();
        if(vis[x]) continue;
        vis[x]=1;
        for(int i=h[x];i;i=ne[i])
        {
            int y=e[i],z=w[i];
            if(dis[y]>dis[x]+z)
            {
                dis[y]=dis[x]+z;
                q.push({-dis[y],y});
            }
        }
    }
}
void solve()
{
    cin>>n;
    for(int i=1;i<=n;i++) cin>>a[i];
    for(int i=1;i<=n;i++) cin>>b[i];
    for(int i=1;i<=n;i++) h[i]=0;
    tot=0;
    for(int i=1;i<=n;i++)
    {
        if(i!=1) add(i,i-1,0);
        add(i,b[i],a[i]);
    }
    dijkstra();
    ll ans=0,sum=0;
    for(int i=1;i<=n;i++)
    {
        sum+=a[i];
        ans=max(ans,sum-dis[i]);
    }
    cout<<ans<<'\n';
}
int main()
{
    #ifndef ONLINE_JUDGE
    freopen("1.in","r",stdin);
    freopen("1.out","w",stdout);
    #endif 
    int T;
    cin>>T;
    while(T--) solve();
    return 0;
}

posted @ 2024-10-24 11:10  zhouruoheng  阅读(20)  评论(0编辑  收藏  举报