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
入力サンプル#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);
}