yokobuttonの不定期で競技プログラミングをするブログ

不定期で解けた競技プログラミングコンテストの問題を載せています。

パナソニックグループプログラミングコンテスト2022(AtCoder Beginner Contest 251) C - Poem Online Judge

問題の要約
ポエムオンラインジャッジ(以下POJ)は提出された文字列に得点をつけるオンラインジャッジ。
POJにN回の提出があった。早い方からi番目の提出では文字列Siが提出されて、得点はTi。(同じ文字列が複数回提出される場合もある)
ただし、POJでは同じ文字列を提出しても得点が等しいとは限らない。
N回の提出のうち、その提出よりも早い提出であって文字列が一致するものが存在しないような提出をオリジナルであると呼ぶ。
また、オリジナルな提出の中で最も得点が高いものを最優秀賞と呼ぶ。ただし、そのような提出が複数ある場合は、最も提出が早いものを最優秀賞とする。
最優秀賞は早い方から何番目の提出か?

制約
1<=N<=10^5
Siは英小文字からなる文字列
Siの長さは1以上10以下
0<=Ti<=10^9

入力
N
S1 T1
S2 T2
...
SN TN

考え方
1,オリジナルなものだけ考えればよい。今回はmap<string,long long>mpでオリジナルかどうか調べる。
2,オリジナルなものだけになったので、同じ文字列はない。よって、文字列を管理する必要はないので、得点と何番目かを管理する。
 これはvector<pair<long long,int>>Tnumで管理する。
3,Tnumを昇順でソートすると最後に一番得点が高いものが固まる。
4,しかし、何番目かも昇順でソートされているので、これから一番早いものを探さなくてはいけない。
 vectorの最後の得点から確認していき、得点が違っているところのものが得点が一番高い中で一番早いもの。

実際のプログラム
#include<iostream>
#include<string>
#include<vector>
#include<map>
#include<algorithm>

using namespace std;

int main(){
  int N;
  cin >> N;
  
  map<string, long long> mp;
  vector<pair<long long, int>> Tnum;
  for(int i = 1; i <= N; ++i){
    string S;
    long long T;
    cin >> S >> T;
    if(mp[S] != 0){
      continue;
    }
    ++mp[S];
    Tnum.push_back(make_pair(T,i));
  }
  
  sort(Tnum.begin(),Tnum.end());
  
  long long T = Tnum[Tnum.size()-1].first;
  int ans = 1;
  for(int i = Tnum.size()-1; i >= 0; --i){
    if(T != Tnum[i-1].first){
      ans = Tnum[i].second;
      break;
    }
  }
  
  cout << ans << endl;
  
  return 0;
}