解:
啊,又不会。。
#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; }