1. 程式人生 > 其它 >AtCoder Beginner Contest 221 題解

AtCoder Beginner Contest 221 題解

AtCoder Beginner Contest 221

A:Seismic magnitude scales

題意:

\((a-b)^{32}\)

思路:

直接求即可。

B:typo

題意:

定義一種操作為交換兩個字串相鄰的字元,問是否能做到至多進行一次操作使得兩個字串相等。

\(len\leq1e5\)

思路:

檢查兩個字串對應位不相等的個數,如果不為 \(0\)\(2\) 則無法完成,否則看兩個不相等字元的是否相鄰。

C:Select Mul

題意:

給定一個數 \(n\)\(1\leq n\leq 10^9\)),把這個數的每個位變成序列的一個元素,問在這個序列的排列找一個位置使得左邊組成的數和右邊組成的數乘積最大 ,輸出乘積。

思路:

依題意模擬即可,在變成序列後可以考慮使用 \(next\_permutation\) 函式獲取下一個排列,在每個排列中暴力列舉分割位置 ,最多進行 \(9! \times 8\) 次。

D:Online games

題意:

給定 \(n\) 個區間 \([~l_i,l_i+r_i-1~]\) ,輸出 \(n\) 行,第 \(i\) 行表示有幾個點恰好屬於 \(i\) 個區間。

思路:

不妨設 \(r_i=r_i+l_i-1\) ,這樣會變得很方便,可以考慮把所有 \(l_i\)\(r_i\) 扔到一個長度為 \(2\times n\) 的序列 \(a\) 裡以便離散化,對他進行排序和去重,避免端點重合但不更新答案的情況。用 \(x_i\)

記錄當前位置被幾條線段覆蓋 ,每次 \(l_i\)\(r_i\) 並更新答案,即 \(x_{l_i}=x_{l_i}+1\)\(x_{r_i}=x_{r_i}-1\) ,對 \(x_i\) 字首和可以得到屬於幾個區間,直接統計答案即可 。

複雜度:\(O(n~log~n)\) ,在找 \(l_i\)\(r_i\) 時可以二分

程式碼:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
ll a[400005],num[400005],x[400005];
ll l[400005],r[400005],n;
map<ll,ll>ans;
int main()
{
    cin>>n;
    for(int i=0;i<n;i++)
    {
        cin>>l[i]>>r[i];
        r[i]+=l[i]-1;
        r[i]++;
        a[2*i]=l[i];
        a[2*i+1]=r[i];
    }
    sort(a,a+2*n);
    int m=unique(a,a+2*n)-a;
    for(int i=0;i<n;i++)
    {
        int lq=lower_bound(a,a+m,l[i])-a;
        int rq=lower_bound(a,a+m,r[i])-a;
        x[lq]++,x[rq]--;
    }
    num[0]=x[0];
    for(int i=1;i<m;i++)
    {
        num[i]=num[i-1]+x[i];
    }
    for(int i=0;i<m;i++)
    {
        ans[num[i]]+=a[i+1]-a[i];
    }
    for(int i=1;i<=n;i++)
    {
        cout<<ans[i]<<" ";   
    }
    system("pause");
}

E:LEQ

題意:

\(\sum _{1\leq i\leq j\leq n}~2^{j-i-1}\times[~a_i\leq a_j~]\)

思路: