Codeforces Round332 部分題解

A. Patrick and Shopping
應用Floyd-Warshall的想法,先把每兩點之間的最短距離更新了,然後最後的結果就是d1 + d2 + d3

#define FOR(a, b, n) for(int (a) = (b); (a) < (n); ++(a))
#define ITE(a, v) for(auto (a) = v.begin(); (a) != v.end(); ++(a))
#define LL long long
#define ALL(v) v.begin(),v.end()
#define ZERO(v) memset(v, 0, sizeof v)
#define NEG(v)  memset(v, -1, sizeof v)
#define F first
#define S second
#define PB push_back
#define MP make_pair
#define MOD 1000000007
#define PI 3.141592653589793
#define INF 5e8
inline long double min(long double a , long double b) {if(a < b)return a; return b;}
inline long double max(long double a , long double b) {if(a < b)return b; return a;}


int d1,d2,d3;
int  main()
{

    cin >> d1 >> d2 >> d3;
    d3 = min(d1 + d2, d3);
    d1 = min(d2 + d3, d1);
    d2 = min(d1 + d3, d2);
    cout << d1 + d2 + d3 << endl;
    return 0;

}

B. Spongebob and Joke
題很簡單,題意很複雜的典型。。
大意就是A是一個長度m的數組,值得範圍[1,n],F是長度n的數組,B也是長度n的數組,對於B有B(i) = F(A(i)),現在已知B,F,求A的解的情況。
因爲F中的值範圍也是[1,n],先建立一個數組將F中每個值對應的index記錄一下,比如說如果F是[1,2,2],那麼record[1] = {0}, record[2] = {1,2},record[3] = {}. 然後遍歷B,對於每個B值,找到其對應的index,如果數量超過一個,那麼肯定有ambiguity,如果數量是0,那麼不可能啦,如果數量是1,繼續check下一個,複雜度O(n)

#define FOR(a, b, n) for(int (a) = (b); (a) < (n); ++(a))
#define ITE(a, v) for(auto (a) = v.begin(); (a) != v.end(); ++(a))
#define LL long long
#define ALL(v) v.begin(),v.end()
#define ZERO(v) memset(v, 0, sizeof v)
#define NEG(v)  memset(v, -1, sizeof v)
#define F first
#define S second
#define PB push_back
#define MP make_pair
#define MOD 1000000007
#define PI 3.141592653589793
#define INF 5e8
inline long double min(long double a , long double b) {if(a < b)return a; return b;}
inline long double max(long double a , long double b) {if(a < b)return b; return a;}


int n;
int m;
int b[100100];
int f[100100];
vector<int> pos[100100];
vector<int> res;
int solve()
{

    bool flag = true;
    FOR(i,0,m)
    {
        int val = b[i];
        if(pos[val].size() > 1)
        {
            flag = false;
        }
        else if(pos[val].size() == 0)
        {
            return -1;
        }
        else
            res.PB(pos[val][0]);

    }
    if(flag == false)
        return 0;
    return 1;

}
int  main()
{

    cin >> n;
    cin >> m;
    FOR(i,0,n)
    scanf("%d", &f[i]);
    FOR(i,0,m)
    scanf("%d", &b[i]);
    FOR(i,0,n)
    {
        pos[f[i]].PB(i);
    }
    int ress = solve();
    if(ress == 1)
    {
        cout << "Possible" << endl;
        FOR(i,0, res.size())
        cout << res[i]  + 1<< " ";
        cout << endl;
    }
    else if(ress ==0)
        cout << "Ambiguity" << endl;
    else
        cout <<"Impossible" << endl;
    return 0;
}

C. Day at the Beach
這道題卡了挺久。。。但是真的不難
題意大概是講將一個unsorted array 分成幾部分,如果將每部分sort以後總的array是sorted的話,那麼這個分塊就是合理的,問最大的合理的分塊是多少。
一開始我打算二分然後驗證分塊是否合理,最後發現思路和直接解是一樣的。
當前塊的最小值一定大於前一塊的最大值,基於此推導的話一定是大於前面的塊的所有的數。那麼當前塊的最大值一定是大於之前的所有的數的,而且是小於後面的塊的最小值。
那麼我們找可能的最大值就行,最大值的條件是大於之前所有的數,他覆蓋的範圍是直到後面的數的最小值大於它。
所以用prefix[i]記錄前i 個數的最大值,suffix[i]記錄從i開始後面的數的最小值。找到一個數發現他是最大值以後就不斷向後找,直到suffx[i] 大於這個最大值。不過我發現直接找prefix[i] <= suffix[i] 和之前的算法等價。

#define FOR(a, b, n) for(int (a) = (b); (a) < (n); ++(a))
#define ITE(a, v) for(auto (a) = v.begin(); (a) != v.end(); ++(a))
#define LL long long
#define ALL(v) v.begin(),v.end()
#define ZERO(v) memset(v, 0, sizeof v)
#define NEG(v)  memset(v, -1, sizeof v)
#define F first
#define S second
#define PB push_back
#define MP make_pair
#define MOD 1000000007
#define PI 3.141592653589793
#define INF 5e8
inline long double min(long double a , long double b) {if(a < b)return a; return b;}
inline long double max(long double a , long double b) {if(a < b)return b; return a;}


int n;
int a[100100];
int pref[100100];
int suff[100100];
int solve()
{
    pref[0] = a[0];
    suff[n - 1] = a[n - 1];
    FOR(i,1,n)
    pref[i] = max(pref[i - 1], a[i]);
    for(int i = n - 2; i >= 0; i--)
        suff[i] = min(suff[i + 1], a[i]);
    int count = 0;
    FOR(i,0,n - 1)
        if(pref[i] <= suff[i + 1])
            count++;
    count++;
    return count;
}
int  main()
{

    cin >> n;
    FOR(i,0,n)
    {
        scanf("%d", &a[i]);
    }
    cout << solve() << endl;
    return 0;

}

D. Spongebob and Squares
感覺C,D應該換一下難度纔對
大意就是對於m*n的一個矩陣,裏面包含的長度爲1,2,3…min(m,n)的正方體矩陣個數爲x個,現在已知x,求可能的m,n。
純數學問題,如果m,n已知,假設m < n, 那麼x = m * n + (m - 1) * (n - 1) + (m - 2) * (n - 2) +… + 1 * (n - m + 1)
設diff = n - m, 那麼x = 1 * (diff + 1) + 2 * (diff + 2) + … + m * (diff + m) = diff * (m + 1) * m / 2 + (m + 1)(m + 2)(2m + 1) / 6
因爲 x <= 1e18,所以m最多等於1e6, 從1開始遍歷m就行,如果存在合理的diff的值,則記錄n = diff + m
記着每次要insert pair(m,n)和pair(n,m)
我用set存得,所以複雜度O(NlgN), N = 1e6,不過應該優化到O(N)是可以的

#define FOR(a, b, n) for(int (a) = (b); (a) < (n); ++(a))
#define ITE(a, v) for(auto (a) = v.begin(); (a) != v.end(); ++(a))
#define LL long long
#define ALL(v) v.begin(),v.end()
#define ZERO(v) memset(v, 0, sizeof v)
#define NEG(v)  memset(v, -1, sizeof v)
#define F first
#define S second
#define PB push_back
#define MP make_pair
#define MOD 1000000007
#define PI 3.141592653589793
#define INF 5e8
inline long double min(long double a , long double b) {if(a < b)return a; return b;}
inline long double max(long double a , long double b) {if(a < b)return b; return a;}


LL x;
set<pair<LL,LL> > res;
LL calc(int k)
{
    LL res = 1;
    res *= k;
    res *= (k + 1);
    res *= (2*k + 1);
    res /= 6;
    return res;
}
void solve()
{
    for(int k = 1; k <= 1e6 + 1 && calc(k) <= x; k++)
    {
        LL temp = x - calc(k);
        LL temp1 = 1LL * k * (k + 1) / 2;
        if(temp % temp1 == 0)
        {
            LL temp2 = temp / temp1;
            res.insert(MP(k,k + temp2));
            res.insert(MP(k + temp2, k));
        }
    }
}
int  main()
{

    cin >> x;
    solve();
    cout << res.size() << endl;
    ITE(i,res)
    cout << i->first << " " << i->second << endl;
    return 0;

}

E. Sandy and Nuts
還沒做,每次都要填不完E的大坑啊。。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章