vijos1287确定的位置

题目:https://vijos.org/p/1287

解:

啊,又不会。。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<map>
using namespace std;
inline int read()
{
  char ch; int ef=0;
  ch=getchar();
  while ((ch<'0')||(ch>'9')) ch=getchar();
  while ((ch>='0')&&(ch<='9')) 
  {
      ef=ef*10+ch-'0';
      ch=getchar();
  }
  return ef;
}
map<string,int>maxs;
//maxs[s]表示s这首歌当前可能的最大(数字最大)的名次是多少
int n,tot,newt[2000],sum[2000];
string s,name[2000],ans[2000];
int main()
{
  scanf("%d",&n);
  for (int i=1;i<=n;i++)
  {
      int a=read(); cin>>s; int b=read(); 
      for (int j=1;j<=a;j++)
      {
        cin>>s;
//newt[b]从目前已给的信息中我们可以知道前b名比前面的名次多出现了几首歌
        if (maxs[s]==0) maxs[s]=b,name[++tot]=s,newt[b]++;
//如果当前这首歌是第一次出现,那么用name记录下歌曲的名字,当前s这首歌最大的名次为b,且前b名中又出现了一首新的歌,所以new[b]++;
        else if (maxs[s]>b) newt[maxs[s]]--,maxs[s]=b,newt[b]++;
//如果说这首歌在前面所给的信息中出现过了,且前面出现时给的范围是前maxs[s]名,且maxs[s]>b,则说明这首歌在前b名中就出现过了new[b]++,在前maxs[s]名中已经不是一首新歌了,maxs[s]--;同时更新s这首歌的最大名次是b
    }
  }
  for (int i=1;i<=tot;i++) sum[i]+=sum[i-1]+newt[i];
//表示在前i名中出现了几首歌,如sum[2]=1,则表示前两名中,已经告诉我们了其中一首歌的名字。
  for (int i=1;i<=tot;i++) ans[maxs[name[i]]]=name[i];
如果name[i]这首歌可以确定名次,那么它的名次一定是maxs[name[i]];
  for (int i=1;i<=tot;i++)
  if ((newt[i]==1)&&(sum[i]==i)) cout<<i<<" "<<ans[i]<<endl;
//如果第i个名次的歌曲可以确定,那么首先sum[i]要等于i即前i名的歌曲名都要给出且newt[i]=1即前i名与前面的名次相比,在给出的歌曲中出现了一首新歌,那么这首新歌就一定是第i名
  return 0;
}
原文地址:https://www.cnblogs.com/2014nhc/p/7058257.html