题目链接:https://ac.nowcoder.com/acm/contest/885/H
3个人一起卡B卡一年,各种水题都没看,难顶。
由于前m个小写在字母地无序对恰好全部出现,我们可以直接算出每个字母的第几个应该在哪个位置。
比如我要确定字母a的第一个在第几个位置,那么就看所有有a的条件中,在第一个a之前的字母总和是多少,再加上a在他自己本身的次序1,就是它所在的位置。
无解的情况要小心,WA了几发。
1、每个字母所在的位置不能超过n
2、一个位置只能放一个字母
3、每个字母的个数在不同的条件中必须一样
4、1-n的位置必须放满
否则无解输出-1
#include<bits/stdc++.h> #define maxl 100010 using namespace std; int n,m; int pos[26][maxl]; int len,mlen[26]; char ch[10]; char s[maxl]; char ans[maxl]; bool in[maxl]; bool flag; inline void prework() { scanf("%d%d",&n,&m); int cnt0,cnt1; memset(mlen,-1,sizeof(mlen)); flag=true; for(int i=1;i<=m*(m-1)/2;i++) { scanf("%s%d",ch,&len); cnt0=cnt1=0; if(len>0) { scanf("%s",s+1); for(int j=1;j<=len;j++) { if(s[j]==ch[0]) { cnt0++; pos[ch[0]-'a'][cnt0]+=cnt1; } else { cnt1++; pos[ch[1]-'a'][cnt1]+=cnt0; } } } if(mlen[ch[0]-'a']==-1) mlen[ch[0]-'a']=cnt0; else if(mlen[ch[0]-'a']!=cnt0) flag=false; if(mlen[ch[1]-'a']==-1) mlen[ch[1]-'a']=cnt1; else if(mlen[ch[1]-'a']!=cnt1) flag=false; } } inline void mainwork() { if(!flag) return; for(int i=0;i<m;i++) for(int j=1;j<=mlen[i];j++) if(pos[i][j]+j<=n) { if(!in[pos[i][j]+j]) { ans[pos[i][j]+j]='a'+i; in[pos[i][j]+j]=true; } else { flag=false; return; } } else { flag=false; return; } for(int i=1;i<=n;i++) if(!in[i]) { flag=false; return; } } inline void print() { if(flag) for(int i=1;i<=n;i++) printf("%c",ans[i]); else puts("-1"); } int main() { prework(); mainwork(); print(); return 0; }