Codeforces Round #568 (Div. 2) AB C1 C2 题解

传送门

A. Ropewalkers

题意:给三个数,每次可以对一个数+1或-1,问最少多少次可以使得三个数两两之间距离>=d。

思路:水题,存进来的排个序,abc依次表示从小到大的。只要考虑b往两边距离满足题意即可。

view code
#include<iostream>
#include<string>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<map>
#include <queue>
#include<sstream>
#include <stack>
#include <set>
#include <bitset>
#include<vector>
#define FAST ios::sync_with_stdio(false)
#define abs(a) ((a)>=0?(a):-(a))
#define sz(x) ((int)(x).size())
#define all(x) (x).begin(),(x).end()
#define mem(a,b) memset(a,b,sizeof(a))
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define rep(i,a,n) for(int i=a;i<=n;++i)
#define per(i,n,a) for(int i=n;i>=a;--i)
#define pb push_back
#define mp make_pair
#define fi first
#define se second
using namespace std;
typedef long long ll;
typedef pair<ll,ll> PII;
const int maxn = 1e5+200;
const int inf=0x3f3f3f3f;
const double eps = 1e-7;
const double pi=acos(-1.0);
const int mod = 1e9+7;
inline int lowbit(int x){return x&(-x);}
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
void ex_gcd(ll a,ll b,ll &d,ll &x,ll &y){if(!b){d=a,x=1,y=0;}else{ex_gcd(b,a%b,d,y,x);y-=x*(a/b);}}//x=(x%(b/d)+(b/d))%(b/d);
inline ll qpow(ll a,ll b,ll MOD=mod){ll res=1;a%=MOD;while(b>0){if(b&1)res=res*a%MOD;a=a*a%MOD;b>>=1;}return res;}
inline ll inv(ll x,ll p){return qpow(x,p-2,p);}
inline ll Jos(ll n,ll k,ll s=1){ll res=0;rep(i,1,n+1) res=(res+k)%i;return (res+s)%n;}
inline ll read(){ ll f = 1; ll x = 0;char ch = getchar();while(ch>'9'||ch<'0') {if(ch=='-') f=-1; ch = getchar();}while(ch>='0'&&ch<='9') x = (x<<3) + (x<<1) + ch - '0',  ch = getchar();return x*f; }
int dir[4][2] = { {1,0}, {-1,0},{0,1},{0,-1} };

ll arr[5];

int main()
{
    ll a, b , c ,d;
    cin>>arr[1]>>arr[2]>>arr[3]>>d;
    sort(arr+1,arr+1+3);
    a = arr[1] , b = arr[2], c = arr[3];
    ll d1 = 0;
    if(b - a < d) d1 += d - (b - a);
    if(c - b < d) d1 += d - (c - b);
    cout<<d1<<endl;
    return 0;
}


B. Email from Polycarp

题意:s串为原串,判断t串是否是在s的基础上在使某若干位置的字符重复出现得到的。

思路:双指针简单模拟一下。p指向原串,q指向目标串。如果s[p] == t[q],就继续往下匹配。若不一样,只有两种可能:1.t串在重复上一个字符。 2. 完全失配,直接退出。 如果p走完了s串且t剩下来的全是重复的,就输出"YES"。否则都为"NO" 。

view code
#include<iostream>
#include<string>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<map>
#include <queue>
#include<sstream>
#include <stack>
#include <set>
#include <bitset>
#include<vector>
#define FAST ios::sync_with_stdio(false)
#define abs(a) ((a)>=0?(a):-(a))
#define sz(x) ((int)(x).size())
#define all(x) (x).begin(),(x).end()
#define mem(a,b) memset(a,b,sizeof(a))
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define rep(i,a,n) for(int i=a;i<=n;++i)
#define per(i,n,a) for(int i=n;i>=a;--i)
#define pb push_back
#define mp make_pair
#define fi first
#define se second
using namespace std;
typedef long long ll;
typedef pair<ll,ll> PII;
const int maxn = 1e6+200;
const int inf=0x3f3f3f3f;
const double eps = 1e-7;
const double pi=acos(-1.0);
const int mod = 1e9+7;
inline int lowbit(int x){return x&(-x);}
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
void ex_gcd(ll a,ll b,ll &d,ll &x,ll &y){if(!b){d=a,x=1,y=0;}else{ex_gcd(b,a%b,d,y,x);y-=x*(a/b);}}//x=(x%(b/d)+(b/d))%(b/d);
inline ll qpow(ll a,ll b,ll MOD=mod){ll res=1;a%=MOD;while(b>0){if(b&1)res=res*a%MOD;a=a*a%MOD;b>>=1;}return res;}
inline ll inv(ll x,ll p){return qpow(x,p-2,p);}
inline ll Jos(ll n,ll k,ll s=1){ll res=0;rep(i,1,n+1) res=(res+k)%i;return (res+s)%n;}
inline ll read(){ ll f = 1; ll x = 0;char ch = getchar();while(ch>'9'||ch<'0') {if(ch=='-') f=-1; ch = getchar();}while(ch>='0'&&ch<='9') x = (x<<3) + (x<<1) + ch - '0',  ch = getchar();return x*f; }
int dir[4][2] = { {1,0}, {-1,0},{0,1},{0,-1} };

ll Map[500];

int main()
{
    int kase;
    cin>>kase;
    while(kase--)
    {
        mem(Map,0);
        string s;  cin>>s;
        string t;  cin>>t;
        for(int i=0; i<s.size();i++) Map[s[i]] ++;
        int p = 0, q = 0;
        while(p<s.size()&&q<t.size())
        {
            if(Map[t[q]]==0) break;
            if(t[q] == s[p]) p++, q++;
            else
            {
                if(q>0&&t[q] == t[q-1])
                {
                    while(q<t.size()&&t[q]!=s[p]&&t[q]==t[q-1]) q++;
                }
                else break;
            }
        }
        if(p<s.size())
        {
                cout<<"NO"<<'\n';
        }
        else
        {
            int flag = 1;
            if(q<t.size())
            for(int i=q; i<t.size();i++) if(t[i]!=t[i-1]) flag = 0;
            if(!flag)
            cout<<"NO"<<'\n';
            else
            cout<<"YES"<<'\n';
        }
    }
    return 0;
}


C1. Exam in BerSU (easy version)

题意:给出n个数,每个数会消耗t[i]的时间,问在m时限的情况下i前面要最少去掉多少人才能保证t[i]放得下

思路:贪心一下,要走的人最少的话肯定是让前面的用时大的人走最好。所以读入一个数就将前i-1个数排序一下。从大往小选即可。

view code
#include<iostream>
#include<string>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<map>
#include <queue>
#include<sstream>
#include <stack>
#include <set>
#include <bitset>
#include<vector>
#define FAST ios::sync_with_stdio(false)
#define abs(a) ((a)>=0?(a):-(a))
#define sz(x) ((int)(x).size())
#define all(x) (x).begin(),(x).end()
#define mem(a,b) memset(a,b,sizeof(a))
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define rep(i,a,n) for(int i=a;i<=n;++i)
#define per(i,n,a) for(int i=n;i>=a;--i)
#define pb push_back
#define mp make_pair
#define fi first
#define se second
using namespace std;
typedef long long ll;
typedef pair<ll,ll> PII;
const int maxn = 1e5+200;
const int inf=0x3f3f3f3f;
const double eps = 1e-7;
const double pi=acos(-1.0);
const int mod = 1e9+7;
inline int lowbit(int x){return x&(-x);}
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
void ex_gcd(ll a,ll b,ll &d,ll &x,ll &y){if(!b){d=a,x=1,y=0;}else{ex_gcd(b,a%b,d,y,x);y-=x*(a/b);}}//x=(x%(b/d)+(b/d))%(b/d);
inline ll qpow(ll a,ll b,ll MOD=mod){ll res=1;a%=MOD;while(b>0){if(b&1)res=res*a%MOD;a=a*a%MOD;b>>=1;}return res;}
inline ll inv(ll x,ll p){return qpow(x,p-2,p);}
inline ll Jos(ll n,ll k,ll s=1){ll res=0;rep(i,1,n+1) res=(res+k)%i;return (res+s)%n;}
inline ll read(){ ll f = 1; ll x = 0;char ch = getchar();while(ch>'9'||ch<'0') {if(ch=='-') f=-1; ch = getchar();}while(ch>='0'&&ch<='9') x = (x<<3) + (x<<1) + ch - '0',  ch = getchar();return x*f; }
int dir[4][2] = { {1,0}, {-1,0},{0,1},{0,-1} };

ll t[maxn];

int main()
{
    ll n = read(), m = read();
    ll cur = 0;
    rep(i,1,n)
    {
        ll x = read();
        sort(t+1,t+i,greater<ll>());
        ll p = 1; ll tmp = m - cur;
        while(tmp < x) tmp += t[p], p++;
        cout<<p-1<<' ';
        t[i] = x;
        cur += x;
    }
    cout<<'\n';
    return 0;
}


C2. Exam in BerSU (hard version)

题意:如上题。

思路:这题数据量加大很多,不能想C1那样莽了。仔细看数据发现t[i]<=100,这是个破题口。也就是说我们完全可以把上一题的思路顺延下来,排序的时候只需要在1~100出现过的数字进行排序就行了。所以我们用一个Map记录一下当前数有没有出现过,没出现过就加入all数组,Map同时计数这个数出现了多少次。然后拿到一个数就对前面的all数组排序(长度不会超过100),从大到小挑就行了。而且all[j]有多少个我们也是知道的,可以在O(1)时间内知道all[j]要挑多少。详见代码。

view code
#include<iostream>
#include<string>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<map>
#include <queue>
#include<sstream>
#include <stack>
#include <set>
#include <bitset>
#include<vector>
#define FAST ios::sync_with_stdio(false)
#define abs(a) ((a)>=0?(a):-(a))
#define sz(x) ((int)(x).size())
#define all(x) (x).begin(),(x).end()
#define mem(a,b) memset(a,b,sizeof(a))
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define rep(i,a,n) for(int i=a;i<=n;++i)
#define per(i,n,a) for(int i=n;i>=a;--i)
#define pb push_back
#define mp make_pair
#define fi first
#define se second
using namespace std;
typedef long long ll;
typedef pair<ll,ll> PII;
const int maxn = 2e5+200;
const int inf=0x3f3f3f3f;
const double eps = 1e-7;
const double pi=acos(-1.0);
const int mod = 1e9+7;
inline int lowbit(int x){return x&(-x);}
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
void ex_gcd(ll a,ll b,ll &d,ll &x,ll &y){if(!b){d=a,x=1,y=0;}else{ex_gcd(b,a%b,d,y,x);y-=x*(a/b);}}//x=(x%(b/d)+(b/d))%(b/d);
inline ll qpow(ll a,ll b,ll MOD=mod){ll res=1;a%=MOD;while(b>0){if(b&1)res=res*a%MOD;a=a*a%MOD;b>>=1;}return res;}
inline ll inv(ll x,ll p){return qpow(x,p-2,p);}
inline ll Jos(ll n,ll k,ll s=1){ll res=0;rep(i,1,n+1) res=(res+k)%i;return (res+s)%n;}
inline ll read(){ ll f = 1; ll x = 0;char ch = getchar();while(ch>'9'||ch<'0') {if(ch=='-') f=-1; ch = getchar();}while(ch>='0'&&ch<='9') x = (x<<3) + (x<<1) + ch - '0',  ch = getchar();return x*f; }
int dir[4][2] = { {1,0}, {-1,0},{0,1},{0,-1} };

ll t[maxn];
vector<ll> all;
map<ll,ll> Map;

int main()
{
    ll n = read(), m = read();
    ll cur = 0;
    rep(i,1,n)
    {
        ll x = read();
        sort(all.begin(), all.end(), greater<ll>());
        ll tmp = m - cur;
        ll need = 0;
        for(int j=0; j< all.size(); j++)
        {
            if(tmp >= x) break;
            ll num = min(Map[all[j]] , ( x - tmp+all[j]-1)/all[j] );
            need += num;
            tmp += num * all[j];
        }
        cout<<need<<' ';
        if(!Map[x]) all.pb(x);
        Map[x]++;
        cur += x;
    }
    cout<<'\n';
    return 0;
}


posted @ 2020-08-21 17:41  TL自动机  阅读(80)  评论(0编辑  收藏  举报
//鼠标点击特效第二种(小烟花)