AtCoder Beginner Contest 140:E - Second Sum
予定があり参加を断念しましたが,やりたくなったので一通り挑戦してみた.
A,Bはなんとか解けた.
Cは問題文の通りにmaxを使って解こうとしたが解説を確認してminを使うことに納得.これ以降問題文に出てくる関数にとらわれないように注意する.
Dは自分の考えがめちゃくちゃで解説を見るとO(N)で解けることを知り納得.
以下Eについてよくわからなかったので記しておく.
問題
{1,2,...,N}の数列が与えられ,長さ2以上の部分列の組み合わせに対して,2番目に大きなものの総和を求める.
自分の解答
int main() {
int n;
cin>>n;
int p[n];
rep(i,n){
cin>>p[i];
}
ll sum=0;
rep(i,n-1){
int second=min(p[i],p[i+1]);
int first=max(p[i],p[i+1]);
for(int j=i+1;j<n;j++){
if(p[j]>first){
int tmp=first;
first=p[j];
second=tmp;
}else{
if(p[j]>second&&p[j]<first)second=p[j];
}
sum+=second;
}
}
cout<<sum;
}
結果
TLE.
今までいくつか見たE問題は手がつかなかったので,TLEを出しただけ進歩ととらえたい.
復習
模範解答(snukeさんのコード)
int main() {
int n;
cin >> n;
vector<int> a(n);
rep(i,n) cin >> a[i];
rep(i,n) a[i]--;
vector<int> idx(n);
rep(i,n) idx[a[i]] = i;
set<int> s;
ll ans = 0;
for (int x = n-1; x >= 0; --x) {
int i = idx[x];
ll c = 0;
{ // calc c
s.insert(i);
vector<int> l(2,-1);
vector<int> r(2,n);
{ // calc l
auto it = s.find(i);
rep(j,2) {
if (it == s.begin()) break;
--it;
l[j] = *it;
}
}
{ // calc r
auto it = s.find(i);
rep(j,2) {
++it;
if (it == s.end()) break;
r[j] = *it;
}
}
vector<int> ls(2);
ls[0] = i-l[0]; ls[1] = l[0]-l[1];
vector<int> rs(2);
rs[0] = r[0]-i; rs[1] = r[1]-r[0];
c = (ll)ls[0]*rs[1] + (ll)ls[1]*rs[0];
}
ans += c*(x+1);
}
cout << ans << endl;
return 0;
}
解説動画を見たが,set,autoについての知識がなさすぎてちんぷんかんぷんだ.知識がなさすぎるので勉強の必要性を感じた.
そもそも自分の書いたコードを少し変えればいける可能性はないのかなと思った.
わからないけど...
この記事が気に入ったらサポートをしてみませんか?