C. Enduring Exodus
从左到右枚举人住的房间,牛住的房间不断往后推。
#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
char str[100010];
int Next[100010];
int calc(int pos,int l,int r){
return max(r-pos,pos-l);
}
int main(){
int n,k;
cin>>n>>k;
scanf("%s",str);
for(int i=n-2;i>=0;i--){
if(str[i+1]=='0'){
Next[i]=i+1;
}else{
Next[i]=Next[i+1];
}
}
int pos = 0;
while(str[pos]!='0'){
pos++;
}
int l = pos;
int r = pos+1;
int cnt = 0;
while(1){
if(str[r]=='0'){
cnt++;
}
if(cnt==k)break;
r++;
}
int ans = calc(pos,l,r);
for(int i=Next[pos];i!=0;i=Next[i]){
if(i>r){
r=Next[r];
l=Next[l];
}
if(r==0)break;
ans = min(ans,max(r-i,i-l));
while(i-l>r-i){
if(r==0)break;
ans = min(ans,max(r-i,i-l));
r=Next[r];
l=Next[l];
if(r==0)break;
ans = min(ans,max(r-i,i-l));
}
if(r==0)break;
}
cout<<ans<<endl;
return 0;
}
D. Robot Rapping Results Report
不妨把胜负当成点的出度和入度来看,读数据的时候维护点的度,当出现有一个点只有出度,一个点只有入度,其他的点均有出度和入度时,那两个特别的点肯定是最大的和最小的,删除顺序已知的点……如此循环直到只剩下0或1个点为止,就能认为是有序的了。
#include <bits/stdc++.h>
#include <unordered_set>
using namespace std;
const int maxn = 100010;
vector<int> win[maxn];
vector<int> lose[maxn];
int l[maxn];
int r[maxn];
int lcnt = 0;
int rcnt = 0;
int lrcnt = 0;
bool ban[maxn];
set<int> Set;
int main(){
int n,m;
int MAX = 0;
int MIN = 0;
cin>>n>>m;
for(int i=1;i<=n;i++){
Set.insert(i);
}
int N=n;
int ans = -1;
for(int i=1;i<=m;i++){
int u,v;
scanf("%d%d",&u,&v);
if(ban[u] || ban[v])continue;
win[u].push_back(v);
lose[v].push_back(u);
l[u]++;
r[v]++;
if(l[u]==1){
lcnt++;
if(r[u]){
lrcnt++;
Set.erase(u);
}
}
if(r[v]==1){
rcnt++;
if(l[v]){
lrcnt++;
Set.erase(v);
}
}
while(lrcnt == N-2 && lcnt==N-1 && rcnt==N-1){
rcnt--;
lcnt--;
auto it = Set.begin();
int winner = *it;
it++;
int loser = *it;
Set.clear();
if(l[loser]){
swap(winner,loser);
}
ban[winner] = 1;
ban[loser] = 1;
for(int tt:win[winner]){
if(ban[tt])continue;
r[tt]--;
if(r[tt]==0){
rcnt--;
if(l[tt]){
lrcnt--;
Set.insert(tt);
}
}
}
for(int tt:lose[loser]){
if(ban[tt])continue;
l[tt]--;
if(l[tt]==0){
lcnt--;
if(r[tt]){
lrcnt--;
Set.insert(tt);
}
}
}
N-=2;
}
if(N<2){
ans = i;
}
}
cout<<ans<<endl;
return 0;
}
E. Intellectual Inquiry
考虑某个字符串,
dp(i)
表示以字符
i
结尾的子序列的个数,那么在字符串后面添加字符
#include <bits/stdc++.h>
#include <unordered_map>
using namespace std;
#define ll long long
char str[1000010];
ll dp[26];
const int mod = 1e9+7;
int lastAppear[26];
int main(){
memset(lastAppear,-1,sizeof(lastAppear));
int n,k;
cin>>n>>k;
scanf("%s",str);
int m = strlen(str);
ll sum = 0;
for(int i=0;i<m;i++){
lastAppear[str[i]-'a'] = i;
ll tmp = dp[str[i]-'a'];
dp[str[i]-'a'] = sum+1;
dp[str[i]-'a'] %= mod;
sum = 0;
for(int j=0;j<k;j++){
sum+=dp[j];
}
}
for(int i=0;i<n;i++){
// find min
int MIN = 1e9;
int minchar=0;
for(int j=0;j<k;j++){
if(lastAppear[j]<MIN){
MIN = lastAppear[j];
minchar = j;
}
}
lastAppear[minchar] = m+i;
ll tmp = dp[minchar];
dp[minchar] = sum+1;
dp[minchar] %= mod;
sum = 0;
for(int j=0;j<k;j++){
sum+=dp[j];
}
}
ll ans = 1;
for(int i=0;i<k;i++){
ans+=dp[i];
ans%=mod;
}
cout<<ans<<endl;
return 0;
}