Codeforces Round #492 (Div. 2) [Thanks, uDebug!] — 赛后补题

B. World Cup

题解:同一个位置的访问时间是 time = i - 1 + k * n(每秒向前移动一步,初始时刻是0),从每个位置的出去时间满足( i - 1 + k * n >= a[ i ] ),然后解出满足不等式的最小的k,代入( i - 1 + k * n),就是从该位置出去的时刻,那么答案就是所有位置中出去时间最早的位置。因为time的大小只和k有关,所以可以直接比较k的大小。

PS:2000人的题FST了,真是气啊。除法中向上取整,分母加上 n - 1,避免判断!!!!!

#include<bits/stdc++.h>
#define ll long long
#define P pair<int,int>
#define pb push_back
#define lson root << 1
#define INF (int)2e9 + 7
#define maxn (int)1e5 + 7
#define rson root << 1 | 1
#define LINF (unsigned long long int)1e18
#define mem(arry, in) memset(arry, in, sizeof(arry))
using namespace std;

int n;
int a[maxn];

int main()
{
    cin >> n;
    int res = INF, ans;
    for(int i = 1; i <= n; i++){
        cin >> a[i];
        int y = (a[i] - i + n) / n;
        if(res > y){
            res = y;
            ans = i;
        }
    }
    cout << ans << endl;
    return 0;
}

 C. Tesla

PS:官方的题解太妙了,将中间两行看成一个循环,一个数移动 2n次,必定访问到这个循环的所有位置,所以暴力枚举就行了,在10000的范围内肯定能做完。如果要求最少移动步数就不知道怎么做了

#include<bits/stdc++.h>
#define ll long long
#define P pair<int, int>
#define PP pair<int,pair<int, int>>
#define pb push_back
#define pp pop_back
#define lson root << 1
#define INF (int)2e9 + 7
#define maxn (int)1e5 + 7
#define rson root << 1 | 1
#define LINF (unsigned long long int)1e18
#define mem(arry, in) memset(arry, in, sizeof(arry))
using namespace std;

int n, k, cnt;
int mp[5][55];

P add[200];
vector<PP> v;

void Inite()
{
    cnt = 0;
    for(int i = 1; i <= n; i++) add[++cnt] = P(2, i);
    for(int i = n; i >= 1; i--) add[++cnt] = P(3, i);
}

int main()
{
    cin >> n >> k;
    Inite();
    for(int i = 1; i <= 4; i++) for(int j = 1; j <= n; j++) cin >> mp[i][j];

    bool flag = false;
    for(int i = 1; i <= n; i++) {
        P x = P(1, i), y = P(4, i);
        if(mp[1][i] == mp[2][i] && mp[1][i]) { v.pb(PP(mp[2][i], x)); mp[2][i] = 0; }
        if(mp[3][i] == mp[4][i] && mp[3][i]) { v.pb(PP(mp[3][i], y)); mp[3][i] = 0; }
        if(!mp[2][i] || !mp[3][i]) flag = true;
    }
    if(!flag) { puts("-1"); return 0; }

    //cout << endl;

    for(int t = 1; t <= 20000; t++) {
    /*
        for(int i = 1; i <= 4; i++) {
            for(int j = 1; j <= n; j++) {
                cout << mp[i][j] << " ";
            }
            cout << endl;
        }
        cout << endl;
        */
     // 枚举每次循环的起始位置
        int pos;
        for(int i = 1; i <= cnt; i++) {
            P tp = add[i];
            if(mp[tp.first][tp.second] == 0){
                pos = i;
                break;
            }
        }
     // 将整个环移动一个位置
        for(int i = 0; i < cnt; i++) {
            int now = (pos - i <= 0 ? pos - i + cnt : pos - i);
            int pre = (now == 1 ? cnt : now - 1);
            //cout << now << " " << pre << endl;

            if(i == cnt - 1){
                mp[add[now].first][add[now].second] = 0;
                continue;
            }

            P x, y;
            x = add[now];
            y = add[pre];

            mp[x.first][x.second] = mp[y.first][y.second];
            if(mp[y.first][y.second]) v.pb(PP(mp[y.first][y.second], x));
        }
       
        for(int i = 1; i <= n; i++) {
            P x = P(1, i), y = P(4, i);
            if(mp[1][i] == mp[2][i] && mp[1][i]) { v.pb(PP(mp[2][i], x)); mp[2][i] = 0; }
            if(mp[3][i] == mp[4][i] && mp[3][i]) { v.pb(PP(mp[3][i], y)); mp[3][i] = 0; }
        }
    }
    int res = (int)v.size();
    cout << (res == 0 ? -1 : res) << endl;
    for(auto i : v) {
        P tp = i.second;
        cout << i.first << " " << tp.first << " " << tp.second << endl;
    }
    return 0;
}

 D. Suit and Tie

PS:又是一道不知道怎么证明的题,比赛的时候2000人过,真是,,,难受! Orz,我们可以从最左的位置开始考虑,对于第一个数来说,它的另一半向左移比它向右移会更优,注意第一个数的位置在最左端,所以它向右移的话必定会增加其他对的移动步数。处理完第一对后,剩下的同样处理。

#include<bits/stdc++.h>
#define ll long long
#define P pair<int, int>
#define PP pair<int,pair<int, int>>
#define pb push_back
#define pp pop_back
#define lson root << 1
#define INF (int)2e9 + 7
#define maxn (int)1e5 + 7
#define rson root << 1 | 1
#define LINF (unsigned long long int)1e18
#define mem(arry, in) memset(arry, in, sizeof(arry))
using namespace std;

int n;
int a[300];

int main()
{
    cin >> n;
    int m = 2 * n;
    for(int i = 1; i <= m; i++) cin >> a[i];
    int res = 0;
    for(int i = 1; i <= m; i += 2) {
        int pos = -1;
        for(int j = i + 1; j <= m; j++) if(a[j] == a[i]) { pos = j; break; }
        for(int j = pos; j > i + 1; j--) {
            swap(a[j], a[j - 1]);
            res++;
        }
    }
    cout << res << endl;
    return 0;
}

 E. Leaving the Bar

PS:多生成几次随机序列然后贪心都能过,不知道为啥

// 调换一下循环的顺序就会WA
#include<bits/stdc++.h> #define ll long long #define P pair<int, int> #define PP pair<int,pair<int, int>> #define pb push_back #define pp pop_back #define lson root << 1 #define INF (int)2e9 + 7 #define maxn (int)1e5 + 7 #define rson root << 1 | 1 #define LINF (unsigned long long int)1e18 #define mem(arry, in) memset(arry, in, sizeof(arry)) using namespace std; P a[maxn]; int n, c[maxn]; ll dis(ll x, ll y) { return sqrt(x * x + y * y); } int main() { cin >> n; for(int i = 0; i < n; i++) cin >> a[i].first >> a[i].second; int x = 0, y = 0; for(int i = n - 1; i >= 0; i--) { if(dis(x + a[i].first, y + a[i].second) <= dis(x - a[i].first, y - a[i].second)) { x += a[i].first; y += a[i].second; c[i] = 1; } else{ x -= a[i].first; y -= a[i].second; c[i] = -1; } } for(int i = 0; i < n; i++) cout << c[i] << " "; cout << endl; return 0; }

 

posted @ 2018-06-25 12:13  天之道,利而不害  阅读(244)  评论(0编辑  收藏  举报