AtCoder初級コンテスト136

AtCoder初級コンテスト136

コンテスト期間:2019年8月4日(日)午後八時〜2019年8月4日(日)午前21時40分

ウェブサイトAtCoder BC-136

いくつかのテストの質問に戻って考えることは角度D.来ました

C - 階段を構築

件名の説明:

すべての山の高さを考えると、左から右に山がn個\(\こんにちは)今、あなたは、最高1回、各山のために次の操作を行うことができ、山の高さが1減少します。

Q.は、左から右へ、最終的な高さを作りを通して、操作上の山の一部を実行することが可能であり、山はシーケンスをドロップされませんでした。あなたが出力可能であれば"Yes"、それ以外の出力を"No"

データ範囲:

\(1 <= N <= 10 ^ 5 \) \(1 <=こんにちは<= 10 ^ 9 \)

ソリューション:

私たちは変革を問うことができます。

二つの配列A、Bがあり、B [I] = A [i]が-1(i∈[1、N])を満たします

以下の条件が満たされるように、彼女は新しいシーケンス構造C、Cかどうかを尋ねました:

  • 任意のi∈[1、N]のために、C [I] = A [I]又はC [I] = B [i]は
  • Cシーケンスが落ちていません

そうでない場合はA [i]を選択する必要があり、以上で前提C [I-1]を満たすように、C [I]を考慮した場合、我々は小さいBを[i]を選択することは明らかです。タイトルは1つのk個の中に落下する場合は、実際には同じです。

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int n,a[N],b[N];
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++)scanf("%d",&a[i]),b[i]=a[i]-1;
    a[n+1]=1e9+1;
    int lst=0;
    for(int i=1;i<=n;i++){
        if(b[i]>=lst)lst=b[i];
        else if(a[i]>=lst)lst=a[i];
        else{puts("No");return 0;}
    }
    puts("Yes");
}

D - 収集チルドレン

件名の説明:

正方形の列にNがあり、各正方形は上に書かれている'L'か、'R'長さの文字列表現でN(添字1つの開始)、及び所定s[1]='R',s[n]='L'

駅の初めに各正方形は、子どもたちは、誰もがされている(10 ^ {100} \)\回以下の動きを:

  • この時点で彼が立った位置は、Lが書かれた場合は、その後、彼はボックスの左側に移動し、右に、逆に。

最後に、各広場に立ってどのように多くの子供たち尋ねます。

データ範囲:

\(2 <= N <= 10 ^ 5 \)

例:

入力サンプル#1

RRLRL

サンプル出力#1

0 1 2 1 1

入力サンプル#2

RRRLLRLLRRRLLLLL

出力サンプル#2

0 0 3 2 0 2 1 0 0 0 4 4 0 0 0 0
ソリューション:

または思考の角度とすることができません。最初は全体として考慮のお子様は、決定するために、しかし、テーブルサイクルをプレイ見つかります\(10 ^ {100} \)第二に答え、それをしないし。

彼は誰に貢献する統計的独立した、独立したに開いて、それぞれの子を考えてみましょう。ルールを見つけることは簡単です:誰もが最終的には「RL」の間のサイクルに移動します次いで、プレIの各点のO(N)時間で、私は、最も近い左側である'R'位置\(R&LT [I] \)、iは右側に最も近い'L'位置\(L [I] \) 。

統計に答え、ポイントがあれば'L'、この最後の点について子どもたちが中になること\(R [i]が\)\(R [i]は+1 \ ) の周りシャッフルの間、唯一の考慮\(10 100 ^ {} \)パリティ缶。このポイントである場合'R'の動作も同様です。短いと(10 ^ {100} \)\パリティ関連します、私も同じquq前に長い時間のために希望します

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10; 
int R[N],L[N];
int cnt[N];
char s[N];
int main(){
    scanf("%s",s+1);
    int n=strlen(s+1),pos=0;
    for(int i=1;i<=n;i++){
        if(s[i]=='R')pos=i;
        R[i]=pos;
    }
    pos=n;
    for(int i=n;i>=1;i--){
        if(s[i]=='L')pos=i;
        L[i]=pos;
    }
    for(int i=1,step;i<=n;i++){
        if(s[i]=='L'){
            step=i-R[i];
            cnt[R[i]+step%2]++;
        }
        else{
            step=L[i]-i;
            cnt[L[i]-step%2]++;
        }
    }
    for(int i=1;i<=n;i++)printf("%d ",cnt[i]);
}

E - マックスGCD

件名の説明:

A.を含むn個の要素の配列があります あなたは、次の操作を行うことができます\([0、K] \ ) 回:

  • 任意に選択\(I、j∈[1、 N] ≠JとIは、\)操作の後、:(1 +愛=あい、AjとAJ- = 1 \)\(負であってもよいことを意味します)

すべての愛を持っているような、最大の正の整数ANSを見つけてください(任意の整数を(xは愛= X * ANS)\です) \

データ入出力フォーマット&範囲:
  • \(2≤N≤500\)
  • \(^1≤Ai≤106 \)
  • \(^0≤K≤109 \)
  • 入力のすべての値は整数です。
例:

入力サンプル#1

2 3
8 20

サンプル出力#1

7

入力サンプル#2

4 5
10 1 2 22

出力サンプル#2

7
ソリューション:

問題の意味は以下の式に来る- Xiが増加動作アイの値を表し、\を((xi∈[-k、K ])\)

\(A1 + X1 = Z1年* \)

\(A2 + X2 = zの2年* \)

\(...... \)

\(AN + XN = ANS *亜鉛\)

すべての方程式ゲイン:

\((A1 + A2 + ... + AN)+ ...(X1 + X2 + ... + XN)= ANS *(Z1 + Z2 + ... +亜鉛)\)

すべての蓄積されたxは0であり、したがってためANS Aは、シーケンスの和の要因でなければなりません基本フレームは、列挙和ANS因子(シーケンスの和)に来て、その後、(ANS)、該当する更新した場合、最終的な答えをチェックすることができます。

課題は、上記の式をトリミングする方法であって、そのような全ての粒子がより大きいまたは0に等しいと等しい和XI Kよりも小さいこと

ビューのサンプル#2ポイントを取る、我々は確認したときに(7):

\(10 +×1 = 7 * Z1 \)

\(1 +×2 = 7 * Z2 \)

\(2 + X3 = 7 * Z3 \)

\(22 + X4 * Z4 = 7 \)

設定プログラムは、x、考えるのは簡単です\(X = - (xmod7)\)または\(。-X xmod7 7 = \) 正当性と最適性一目で:接触タイトルことが理解される
\ [\左\ {\アレイ開始{X1} = {C} -3 + 4 ......①\\ X2 = -1または+ 6 ......②\\ X3 = -2 + 5 ......③\\ X4 = -1または+ 6 ......④\\ \端{
右\アレイ}。\] だから、今問題は、左または取る権利のいずれかを取って、各XIのために、直面しています最後のxの合計は0であり、全てのX / K 2の絶対値の和が等しい未満であるように

ここで貪欲スキームこのような問題は、次のとおりです。

-降順に前の列に係るXiが最初の徴候、描かを無視しました1 1 2 3

次の時間軸の列挙は、次に左右のK未満に等しいと等しいと同様に、可能ANS。

明らかに正し、8の下に理解するためのコードで感情的な表情。

#include<bits/stdc++.h>
using namespace std;
#define int long long
int sum=0;
int a[510],ans,n,k;
int sum1[510],sum2[510],p[510];
bool check(int x){
    int cnt=0;
    for(int i=1;i<=n;i++)p[i]=a[i]%x;
    sort(p+1,p+n+1);
    for(int i=1;i<=n;i++)sum1[i]=sum1[i-1]+p[i];
    for(int i=n;i>=1;i--)sum2[i]=sum2[i+1]+x-p[i];
    int mi=k;
    for(int i=1;i<=n;i++){
        if(sum1[i]==sum2[i+1]){
            if(sum1[i]<=k)return 1;
            else return 0;
        }
    }
    return 0;
}
signed main(){
    scanf("%lld%lld",&n,&k);
    for(int i=1;i<=n;i++)scanf("%lld",&a[i]),sum+=a[i];
    for(int i=1;i*i<=sum;i++)if(sum%i==0){
        if(check(i))ans=max(ans,i);
        if(check(sum/i))ans=max(ans,sum/i);
    }
    cout<<ans;
}

F - 同梱のポイント

件名の説明:

座標と、所定のn点(\ \は(XI、YI) )表される、但し、n個の点Sの構成、非空集合のS Tのためのすべての要求の集合\(F(T)\)合成。

機能のために\(F(T)\)以下のように定義される:T設定点が含まれる、xの最小値である\(Xminと\)のXの最大\(Xmaxの\) 最小Y値\(Yminと\)のY-最大\(Ymaxと\) 満足:関数の値\(Xminと<= xで<= XmaxのとyMinの<= Y <= Ymaxの\ ) の点(x、y)の数。

データの入出力フォーマット&スコープ
  • \(1≤N≤2×10 ^ 5 \)
  • \( - 10 ^9≤xi、yi≤10^ 9 \)
  • \(XI≠XJ(I≠J)\)\(YI≠YJ(I≠J)\)
  • 入力のすべての値は整数です。
例:

入力サンプル#1

3
-1 3
2 1
3 -2

サンプル出力#1

13

サンプル#1の説明

入力サンプル#2

10
19 -11
-3 -12
5 3
3 -15
8 -14
-9 -20
10 -9
0 2
-7 17
6 -6

出力サンプル#2

7222
ソリューション:

それを行う方が良いと思い権角度を探します。

アイデアは、1ステップ:答えのそれぞれ独立したポイントの寄与を。

ステップ2考える:各点のためのセットを備えている必要はなく、最終的にはプログラムの総数は、[保存]をクリックします。(あなたが行うことができます場合はもちろん、それは比較的簡単なのは逆になります)

予備知識:n個の点のセットを含むため、それが空でない集合数\(2 ^ N-1 \ )

この質問はすべてそこにあります。

注質問があることを確認するために直面\(XI≠XJ、YJのYI≠\)

第1の離散座標を見て、その後に応じてソート各点のx座標。

図イエロードットが指すように現在のトラバースを表す\(X \)

それぞれ含む領域を有する2つの領域内の点の数\(S [X] [を1] \) \(S [X] [2] \)を表しは、であってもよい\(O(nlogn)\)のメンテナンス時間はフェンウィックツリーを慣れます。領域III、領域の4番中点は後方再度掃引、同じ統計的手法です。

今、私たちは、含まれている各領域のポイント数に来ます。以下のために\(X \)この点で、我々は統計的である今の質問:xのセットの数が含まれていません

プログラムが図4緑豊かなエリアマイナス総図パープルの4つのプログラム領域を合計ことは明らかです。

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=2e5+10,mod=998244353;
int a[N],b[N],c[N],ans;
int s[N][3],two[N],n;
struct node{
    int x,y;
}p[N];
inline bool cmp(node p,node q){return p.x<q.x;}
void add(int x){while(x<=n)c[x]++,x+=x&(-x);}
int sum(int x){
    int res=0;
    while(x){
        res+=c[x];
        x-=x&(-x);
    }
    return res;
}
void calc(int tot,int d){
    ans=(ans+(two[tot]-1)*d%mod)%mod;
}
signed main(){
    scanf("%lld",&n);
    two[0]=1;
    for(int i=1;i<=n;i++)two[i]=two[i-1]*2%mod;
    for(int i=1;i<=n;i++){
        scanf("%lld%lld",&p[i].x,&p[i].y);
        a[i]=p[i].x;
        b[i]=p[i].y;
    }
    sort(a+1,a+n+1);sort(b+1,b+n+1);
    sort(p+1,p+n+1,cmp);
    for(int i=1;i<=n;i++){
        p[i].x=lower_bound(a+1,a+n+1,p[i].x)-a;
        p[i].y=lower_bound(b+1,b+n+1,p[i].y)-b;
    }
    for(int i=1;i<=n;i++){
        int y=p[i].y;
        s[i][2]=sum(y-1),s[i][1]=i-s[i][2]-1;
        add(y);
    }
    memset(c,0,sizeof(c));
    for(int i=n;i>=1;i--){
        int y=p[i].y;
        int s4=sum(y-1),s3=n-i-s4;
        int tmp=ans;
        calc(s[i][1]+s3,1);
        calc(s[i][1]+s[i][2],1);
        calc(s[i][2]+s4,1);
        calc(s3+s4,1);
        calc(s[i][1],-1);
        calc(s[i][2],-1);
        calc(s3,-1);
        calc(s4,-1);    
        add(y);
    }
    printf("%lld",(n*(two[n]-1)%mod-ans+mod)%mod);
}

おすすめ

転載: www.cnblogs.com/Tieechal/p/11303995.html