Educational Codeforces Round 18

Educational Codeforces Round 18 

A. New Bus Route

排个序找最小的差值

view code
//#pragma GCC optimize("O3")
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<bits/stdc++.h>
using namespace std;
function<void(void)> ____ = [](){ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);};

void solve(){
    int n;
    cin >> n;
    vector<int> vec(n);
    for(int &x : vec) cin >> x;
    sort(vec.begin(),vec.end());
    map<int,int> msk;
    for(int i = 1; i < n; i++) msk[vec[i]-vec[i-1]]++;
    cout << msk.begin()->first << ' ' << msk.begin()->second << endl;
}
int main(){
    #ifndef ONLINE_JUDGE
    freopen("Local.in","r",stdin);
    freopen("ans.out","w",stdout);
    #endif
    solve();
    return 0;
}

B.Counting-out Rhyme

按题意模拟即可

view code
//#pragma GCC optimize("O3")
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<bits/stdc++.h>
using namespace std;
function<void(void)> ____ = [](){ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);};

void solve(){
    ____();
    int n, k;
    static bool vis[200];
    cin >> n >> k;
    int cur = 0;
    memset(vis,0,sizeof(vis));
    for(int t = 0; t < k; t++){
        int x; cin >> x;
        x %= (n-t);
        for(int i = 0; i < x; i++){
            while(vis[(cur+1)%n]) cur = (cur + 1) % n;
            cur = (cur + 1) % n;
        }
        vis[cur] = true;
        cout << cur + 1 << ' ';
        while(vis[(cur+1)%n]) cur = (cur + 1) % n;
        cur = (cur + 1) % n;
    }
    cout << endl;
}
int main(){
    #ifndef ONLINE_JUDGE
    freopen("Local.in","r",stdin);
    freopen("ans.out","w",stdout);
    #endif
    solve();
    return 0;
}

C. Divide by Three

先去掉前导零,然后分模(3)余数分类讨论

(0)直接输出

(1)找一个模(3)(1)的或者两个模(3)(2)

(2)找一个模(3)(2)的或者两个模(3)(1)

保留最长的即可

注意判断(0)的情况

view code
//#pragma GCC optimize("O3")
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<bits/stdc++.h>
using namespace std;
function<void(void)> ____ = [](){ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);};
const int MAXN = 1e5+7;
char s[MAXN];
int n;
void solve(){
    cin >> s + 1;
    n = strlen(s+1);
    reverse(s+1,s+1+n);
    bool havez = false;
    for(int i = 1; i <= n; i++) if(s[i]=='0') havez = true;
    int tot = 0;
    for(int i = 1; i <= n; i++) tot += s[i] - '0';
    while(n and s[n]=='0') n--;
    if(!n){
        cout << 0 << endl;
        return;
    }
    if(tot%3==0){
        reverse(s+1,s+1+n);
        cout << s + 1 << endl;
        return;
    }else if(tot%3==2){
        string ss(s+1,s+1+n);
        string s1(""), s2 = s1;
        int pos = -1;
        for(int i = 0; i < n; i++) if((ss[i] - '0') % 3==2){
            pos = i;
            break;
        }
        if(pos!=-1){
            ss[pos] = 'a';
            string sb("");
            for(int i = 0; i < n; i++) if(isdigit(ss[i])) sb+=ss[i];
            while(!sb.empty() and sb.back()=='0') sb.pop_back();
            s1 = sb;
        }
        ss = string(s+1,s+1+n);
        int p1 = -1, p2 = -1;
        for(int i = 0; i < n; i++) if((ss[i] - '0') % 3 == 1){
            if(p1==-1) p1 = i;
            else p2 = i;
            if(p2!=-1) break;
        }
        if(p2!=-1){
            ss[p1] = ss[p2] = 'a';
            string sb("");
            for(int i = 0; i < n; i++) if(isdigit(ss[i])) sb+=ss[i];
            while(!sb.empty() and sb.back()=='0') sb.pop_back();
            s2 = sb;
        }
        if(s1.empty() and s2.empty()){
            if(havez) cout << "0" << endl;
            else cout << -1 << endl;
        }else{
            reverse(s1.begin(),s1.end());
            reverse(s2.begin(),s2.end());
            if(s1.length() > s2.length()) cout << s1 << endl;
            else cout << s2 << endl;
        }
    }else{
        string ss(s+1,s+1+n);
        string s1(""), s2 = s1;
        int pos = -1;
        for(int i = 0; i < n; i++) if((ss[i] - '0') % 3==1){
            pos = i;
            break;
        }
        if(pos!=-1){
            ss[pos] = 'q';
            string sb("");
            for(int i = 0; i < n; i++) if(isdigit(ss[i])) sb+=ss[i];
            while(!sb.empty() and sb.back()=='0') sb.pop_back();
            s1 = sb;
        }
        ss = string(s+1,s+1+n);
        int p1 = -1, p2 = -1;
        for(int i = 0; i < n; i++) if((ss[i] - '0') % 3 == 2){
            if(p1==-1) p1 = i;
            else p2 = i;
            if(p2!=-1) break;
        }
        if(p2!=-1){
            ss[p1] = ss[p2] = 'a';
            string sb("");
            for(int i = 0; i < n; i++) if(isdigit(ss[i])) sb+=ss[i];
            while(!sb.empty() and sb.back()=='0') sb.pop_back();
            s2 = sb;
        }
        if(s1.empty() and s2.empty()){
            if(havez) cout << "0" << endl;
            else cout << -1 << endl;
        }else{
            reverse(s1.begin(),s1.end());
            reverse(s2.begin(),s2.end());
            if(s1.length() > s2.length()) cout << s1 << endl;
            else cout << s2 << endl;
        }
    }
}
int main(){
    #ifndef ONLINE_JUDGE
    freopen("Local.in","r",stdin);
    freopen("ans.out","w",stdout);
    #endif
    solve();
    return 0;
}

D. Paths in a Complete Binary Tree

观察后可以发现每一层的编号的(lowbit)都是相同的,往上一层,(lowbit)(1),往下一层(lowbit)(1)

然后直接一步步转移即可

view code
//#pragma GCC optimize("O3")
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<bits/stdc++.h>
using namespace std;
function<void(void)> ____ = [](){ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);};
typedef long long int LL;
#define lowbit(x) ((x) & -(x))

void solve(){
    ____();
    LL n; cin >> n;
    int q; cin >> q;
    while(q--){
        LL u; string s;
        cin >> u >> s;
        for(auto &ch : s){
            if(ch=='U'){
                if(u==(n+1)/2) continue;
                if(lowbit(u+lowbit(u))==lowbit(u)*2) u += lowbit(u);
                else u -= lowbit(u);
            }else if(ch=='L'){
                if(lowbit(u)==1) continue;
                u -= (lowbit(u) / 2);
            }else if(ch=='R'){
                if(lowbit(u)==1) continue;
                u += (lowbit(u) / 2);
            }
        }
        printf("%I64d
",u);
    }
}
int main(){
    #ifndef ONLINE_JUDGE
    freopen("Local.in","r",stdin);
    freopen("ans.out","w",stdout);
    #endif
    solve();
    return 0;
}

E.Colored Balls 

可以发现块的大小和块的数量不会同时超过(sqrt {A_{min}})

那么我们枚举块的大小来做就好了

注意一些特殊情况

view code
//#pragma GCC optimize("O3")
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<bits/stdc++.h>
using namespace std;
function<void(void)> ____ = [](){ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);};
typedef long long int LL;
const int MAXN = 555;
const int N = 4e4+7;
void solve(){
    static int n, A[MAXN];
    cin >> n;
    for(int i = 1; i <= n; i++) cin >> A[i];
    LL ret = INT_FAST64_MAX;
    auto check = [&](int k){
        LL cnt = 0;
        bool ok = true;
        for(int i = 1; i <= n; i++){        // k and k + 1
            if(A[i]%(k+1)==0){
                cnt += A[i] / (k+1);
                continue;
            }
            if(k - A[i] % (k+1) <= A[i] / (k+1)){
                cnt += A[i] / (k + 1) + 1;
                continue;
            }
            cnt += A[i] / k;
            if(A[i]%k > A[i]/k){
                ok = false;
                break;
            }
        }
        return ok ? cnt : INT64_MAX;
    };

    for(int k = 1; k <= N; k++){
        ret = min(ret,check(k));
        if(A[1]/k) ret = min(ret,check(A[1]/k));
        if(A[1]/k-1>0) ret = min(ret,check(A[1]/k-1));
    }
    cout << ret << endl;
}
int main(){
    #ifndef ONLINE_JUDGE
    freopen("Local.in","r",stdin);
    freopen("ans.out","w",stdout);
    #endif
    solve();
    return 0;
}

F. Mages and Monsters

考虑维护出每秒造成(x)点伤害的最小魔法消耗

我们把每次学习的技能看作二维笛卡尔坐标系上的点,横坐标是每秒伤害,纵坐标是每秒消耗

我们希望造成相同伤害的情况下用尽量少的(MP),那么我们可以动态维护一个下凸包

对于每次查询,我们找到对应的平均伤害即(h/t)对应的位置,如果找不到或者需要的消耗大于了总的(MP)就输出(NO)否则输出(YES)

view code
//#pragma GCC optimize("O3")
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<bits/stdc++.h>
using namespace std;
function<void(void)> ____ = [](){ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);};
typedef pair<double,double> pdd;
typedef long long int LL;
const int M = 1000000;
const double eps = 1e-9;
int n;
double m;

set<pdd> S;
double operator *(pdd A, pdd B){ return A.first * B.second - A.second * B.first; }
pdd operator -(pdd a, pdd b){ return {a.first - b.first,a.second - b.second}; }
double X(pdd a, pdd b, pdd c){ return  (b-a) * (c-a); }

void try_insert(double damage, double cost){
    pdd p = {damage,cost};
    auto it = S.lower_bound({p.first,0});
    if(it!=S.end() and it->second<=p.second) return;
    auto pre = it; --pre;
    if(it!=S.end() and X(*pre,p,*it)<=eps) return;
    it = S.insert(p).first;
    pre = it; pre--;
    while(pre!=S.begin()){
        auto ppre = pre; ppre--;
        if(X(*ppre,*pre,*it)<=eps) S.erase(pre--);
        else break;
    }
    auto nxt = it; nxt++;
    while(nxt!=--S.end() and nxt!=S.end()){
        auto nnxt = nxt; nnxt++;
        if(X(*it,*nxt,*nnxt)<=eps) S.erase(nxt++);
        else break;
    }
}
bool test(double t, double h){
    auto it = S.lower_bound({h/t,0});
    if(it==S.end()) return false;
    auto pre = it; pre--;
    double cost = (it->second - pre->second) / (it->first - pre->first) * (h/t - pre->first) + pre->second;
    return m - cost * t >= -eps;
}
void solve(){
    ____();
    cin >> n >> m;
    S.insert({0,0});
    int lastans = 0;
    for(int i = 1; i <= n; i++){
        int k, a, b;
        cin >> k >> a >> b;
        a = (a + lastans) % M + 1;
        b = (b + lastans) % M + 1;
        if(k==1) try_insert(a,b);
        else{
            if(test(a,b)) puts("YES"), lastans = i;
            else puts("NO");
        }
    }
}
int main(){
    #ifndef ONLINE_JUDGE
    freopen("Local.in","r",stdin);
    freopen("ans.out","w",stdout);
    #endif
    solve();
    return 0;
}
原文地址:https://www.cnblogs.com/kikokiko/p/13514255.html