Codeforces Round #600 (Div. 2)

A. Single Push

给定数组A,B,能否选取A中连续一段把A变得跟B相同

#include<bits/stdc++.h>
using namespace std;
#define int long long 
#define si signed
#define pb push_back 
#define fi first
#define se second
#define endl '
'
#define P pair<int,int>
int t,n;
int A[100000+5];
int B[100000+5]; 
signed main()
{
    scanf("%I64d",&t);
    while(t--){
        scanf("%I64d",&n);
        for(int i=0;i<n;i++){
            scanf("%I64d",&A[i]);
        }
        for(int i=0;i<n;i++){
            scanf("%I64d",&B[i]);
        }
        bool f=0;
        int a=-1;
        for(int i=0;i<n;i++){
            A[i]=B[i]-A[i];
            if(A[i]<0){
                cout<<"No"<<endl;
                f=1;
                break;
            }
        }
        int cnt =0;
        if(!f){
            for(int i=0;i<n;i++){
                if(A[i]&&cnt==0){
                    cnt++;
                    while(i+1<n){
                        if(A[i]==A[i+1]){
                            i++;
                        }
                        else if(A[i]!=A[i+1]&&A[i+1]!=0){
                            puts("No");
                            f=1;
                            break;
                        }
                        else break;
                    }
                }
                else if(A[i]&&cnt!=0){
                    puts("No");
                    f=1;
                    break;
                }
                if(f) break;
            }
            if(!f)puts("Yes");
        }
 
    }
 
}

B. Silly Mistake

给定一个数组,要求给它分段

每一段出现了 i 必须出现 -i,且i要在-i之前出现

同一段不能出现两次相同的 i

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define si signed
#define pb push_back
#define fi first
#define se second
#define endl '
'
#define P pair<int, int>
int t, n;
int A[100000 + 5];
int B[1000000 + 5];
vector<int> ans;
int C[1000000+5];
signed main()
{
    t = 1;
    while (t--)
    {
        scanf("%I64d", &n);
        for (int i = 1; i <= n; i++)
        {
            scanf("%I64d", &A[i]);
        }
        if (n & 1 || A[1] < 0)
        {
            puts("-1");
        }
        else
        {
            bool f = 0;
            int cnt = 0;
            ans.pb(0);
            for (int i = 1; i <= n; i++)
            {
                if (A[i] < 0 && B[-A[i]] == 0)
                {
                    puts("-1");
                    f = 1;
                    break;
                }
                else if (A[i] > 0)
                {
                    B[A[i]]++;
                    C[A[i]]++;
                    cnt++;
                    if(C[A[i]]>1){
                        puts("-1");
                        f=1;
                        break;
                    }
                }
                else
                {
                    B[-A[i]]--;
                    cnt--;
                    if (cnt == 0)
                    {
                        int t=ans[ans.size()-1];
                        ans.pb(i);
                        while(t<=i){///C数组复原
                            if(A[t]>0)C[A[t]]=0;
                            t++;
                        }
                        
                    }
                }
            }
            if (f==0&&cnt != 0)
            {
                cout << "-1" << endl;
                f = 1;
            }
 
            if (!f)
            {
                cout << ans.size()-1 << endl;
                for (int i = 0; i + 1 < ans.size(); i++)
                {
                    cout << ans[i + 1] - ans[i] << ' ';
                }
            }
        }
    }
}

C. Sweets Eating

给定n个糖,每个糖有一个甜度值ai。

每天最多吃m个糖,第i天吃甜度为aj会产生aj*i的代价

输出n个数,第k个数代表吃k个糖最小总代价

排序后模拟 TLE

维护一下每次产生的元素 TLE

维护一下前缀 AC

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define si signed
#define pb push_back
#define fi first
#define se second
#define endl '
'
#define P pair<int, int>
int t, n,m;
int A[200000 + 5];
int B[200000+5];
signed main()
{
    scanf("%I64d%I64d",&n,&m);
    for(int i=1;i<=n;i++){
        scanf("%I64d",&A[i]);
    }
    sort(A+1,A+1+n);
    int ans=0;
    for(int i=1;i<=n;i++){
        int x=(i-1)/m+1;
        int t=i%m;
        if(i%m==0){
           t=m;
        }
 
        int j=1;
        B[t]+=A[t+(x-1)*m];///更新一下前缀
        ans+=B[t];
        cout<<ans<<' ';
    }
 
     
}

D. Harmonious Graph

给定一个无向图,顶点从1到 n

Harmonious Graph:若i<j,且i,j连通则 i与i+1,i+2,...j-1都要连通

求加多少边后能使该图变为Harmonious Graph

先找每个连通分量中的最大最小顶点

按最小顶点排序

从小到大把中间不连通的节点所在连通分量并进来

并查集维护一下连通关系

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define si signed
#define pb push_back
#define fi first
#define se second
#define endl '
'
 
int t, n,m;
vector<int>G[200005];
int ma,mi;
int vis[200005];
void dfs(int x,int y)
{
    for(int i=0;i<G[x].size();i++){
        if(!vis[G[x][i]]){
            vis[G[x][i]]=y;
            mi=min(G[x][i],mi);
            ma=max(G[x][i],ma);
            dfs(G[x][i],y);
        }
    }
}
struct P{
    int fi,se;
    int id;
};
bool cmp(P a,P b)
{
    return a.fi<b.fi;
}
P A[200005];
int fd(int x)
{
    return (vis[x]==x?x:vis[x]=fd(vis[x]));
}
signed main()
{
    int n,m;
    scanf("%I64d%I64d",&n,&m);
   
    int a,b;
    for(int i=1;i<=m;i++){
        scanf("%I64d%I64d",&a,&b);
        G[a].push_back(b);
        G[b].push_back(a);
    }
    int cnt=0;
    for(int i=1;i<=n;i++){
        if(!vis[i]){
            vis[i]=i;
            mi=ma=i;
            dfs(i,i);
            A[cnt].fi=mi;
            A[cnt].se=ma;
            A[cnt++].id=i;
        }
    }
    for(int i=1;i<=n;i++)if(!vis[i])vis[i]=i;
    
    int _a=1,ans=0;
    sort(A,A+cnt,cmp);
    for(int i=0;i<cnt;i++){
        if(A[i].fi==A[i].se)continue;
        else if(A[i].se>_a){
            for( _a=max(_a,A[i].fi);_a<=A[i].se;_a++){
                if(fd(vis[A[i].id])!=fd(vis[_a])){
                    ans++;
                    vis[fd(vis[_a])]=fd(vis[A[i].id]);
                }
            }
        }else continue;
    }
    cout<<ans<<'
';
 
 
}

E. Antenna Coverage

x轴上n个点,每个点有个辐射半径,[xi-si,xi+si]为其覆盖范围,辐射半径拓展1消耗代价为1

要把x轴上[1,m]的所有整点覆盖掉

求最小代价

dp[i]:表示下把从[1,i]所有整点覆盖掉的最小代价

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define si signed
#define pb push_back
#define fi first
#define se second
#define endl '
'
#define sc(x) scanf("%I64d", &x);
int n, m;
int A[100005];
int B[100005];
int dp[100004];
si main()
{
    sc(n)sc(m)
    for(int i=1;i<=n;i++){
        sc(A[i])sc(B[i])
    }
    for(int i=1;i<=m;i++){
        dp[i]=1e18;
        for(int j=1;j<=n;j++){
            dp[i]=min(dp[i],min(max(max(abs(i-A[j])-B[j]/**要把i覆盖掉**/,0ll),(abs(1-A[j])-B[j])/**必须把1覆盖到**/),dp[A[j]-abs(i-A[j])-1<0?0:A[j]-abs(i-A[j])-1]/**dp[0]=0**/+max(abs(i-A[j])-B[j],0ll)));
        }
    }
    cout<<dp[m]<<'
';
}
原文地址:https://www.cnblogs.com/liulex/p/11885749.html