第一次 div2 从 A 冲 到 E 呢!!!
从来没有靠手速上过分/fad。每次都是靠做难题上分。这次排在 5 题的倒数前 10 名着实有点不甘心呢!!!罚时吃满不用慌!!!不过没事!!!!咱是 OI 赛制,不过记得多写个拍!!
不过下一次打 CF 都是寒假了吧
https://codeforces.com/contest/1721
A
#include <bits/stdc++.h>
//#define int long long
#define pb push_back
using namespace std;
char s[6];
int ct[100];
void solve() {
memset(ct,0,sizeof(ct));
cin>>s[1]>>s[2]>>s[3]>>s[4];
for(int i=1;i<=4;i++) {
++ct[s[i]-'a'];
// if(ct[s[i]-'a']>mx) mx=ct[s[i]-'a'];
}
int cnt1=0,cnt2=0,cnt3=0,cnt4=0;
for(int i=0;i<26;i++) {
if(ct[i]==1) ++cnt1;
else if(ct[i]==2) ++cnt2;
else if(ct[i]==3) ++cnt3;
else if(ct[i]==4) ++cnt4;
}
if(cnt4) {
cout<<"0\n";
} else if(cnt3) {
cout<<"1\n";
} else if(cnt2) {
if(cnt2==2) {
cout<<"1\n";
} else cout<<"2\n";
} else cout<<"3\n";
}
signed main() {
cin.tie(0); ios::sync_with_stdio(false);
int T; cin>>T; while(T--) solve();
return 0;
}
B
#include <bits/stdc++.h>
//#define int long long
#define pb push_back
using namespace std;
int n,m,x,y,d;
void solve() {
cin>>n>>m>>x>>y>>d;
int res=n-1+m-1;
if(x-d>1&&y+d<m) {
cout<<res<<'\n';
return ;
}
if(x+d<n&&y-d>1) {
cout<<res<<'\n'; return ;
}
cout<<"-1\n";
}
signed main() {
cin.tie(0); ios::sync_with_stdio(false);
int T; cin>>T; while(T--) solve();
return 0;
}
C
有点难度!赛时先写了 D 再来挑战 C!
考虑若 \(a_i\) 匹配 \(b_j\),那么只要满足 2 个必要条件就能充分了。
-
\(a_i\le b_j\)
-
把 \(a_i,b_j\) 去掉,序列 \(a\),序列 \(b\),对于每个 \(a\) 都能选到 \(b\)。用形式化表达一下,显然 \(a_i\) 选之前 \(a_j,j\in[i+1,n]\) 都得先选好,记 \(a_i\) 能匹配序列 \(b\) 的 \({pp_i}\) 个数,显然要满足 \(n-i+1\le pp_i\)。然后显然我们要维护这个式子,记 \(v_i=pp_i-(n-i+1)\),显然若合法就是 \(\min v_i \ge 0\)。考虑去掉 \(a_i\),那么就是 \(\forall j\in [1,i),v_j+1\),即前面的竞争对手少了一个。去掉 \(b_j\) 同理。
然后我们会发现我们的式子仅跟原先 \(v_i=0\) 的有关,因为至多 \(-1\) 嘛。考虑大于等于 \(i\) 的已经加 \(1\) 了,显然没啥事,于是扫描线+ multiset 维护下第二个东西就好了。
#include <bits/stdc++.h>
//#define int long long
#define pb push_back
using namespace std;
const int N=(int)(2e5+5);
int n,a[N],b[N],ans[N],v[N],pp[N];
//
//bool check(int x,int y) {
// for(int i=1;i<x;i++) v[i]++;
// for(int i=1;i<=n;i++) {
// if(pp[i]<=y) --v[i];
// }
// // v[i]=0 pp[i]<=y i>x
//// int mi=0x3f3f3f3f;
// bool fl=1;
// for(int i=1;i<=n;i++) {
// if(i!=x&&v[i]<0) fl=0;
// }
// for(int i=1;i<x;i++) --v[i];
// for(int i=1;i<=n;i++) if(pp[i]<=y) ++v[i];
// return fl;
//}
multiset<int>s;
bool check(int x,int y) {
if(s.empty()) return 1;
auto qwq=s.upper_bound(y);
if(qwq==s.end()) return 0;
// cout<<x<<" "<<y<<" "<<*qwq<<'\n';
if(qwq==s.begin()) return 1;
// if()
return 0;
}
void solve() {
cin>>n; s.clear();
for(int i=0;i<=n+1;i++) ans[i]=a[i]=b[i]=0;
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=1;i<=n;i++) cin>>b[i];
for(int i=1;i<=n;i++) {
pp[i]=lower_bound(b+1,b+1+n,a[i])-b;
v[i]=(n-pp[i]+1)-(n-i+1);
// cout<<v[i]<<" "<<pp[i]<<'\n';
}
// cout<<check(1,1)<<'\n';
for(int i=n;i>=1;i--) {
int l=pp[i],r=n,res=0;
while(l<=r) {
int mid=(l+r)>>1;
if(check(i,mid)) r=mid-1,res=mid;
else r=mid-1;
}
ans[i]=b[res]-a[i];
if(v[i]==0) {
s.insert(pp[i]);
}
}
for(int i=1;i<=n;i++) cout<<ans[i]<<' ';
cout<<'\n';
s.clear();
for(int i=n;i>=1;i--) {
int l=pp[i],r=n,res=0;
while(l<=r) {
int mid=(l+r)>>1;
if(check(i,mid)) l=mid+1,res=mid;
else r=mid-1;
}
ans[i]=b[res]-a[i];
if(v[i]==0) {
s.insert(pp[i]);
}
}
for(int i=1;i<=n;i++) cout<<ans[i]<<' ';
cout<<'\n';
}
signed main() {
cin.tie(0); ios::sync_with_stdio(false);
int T; cin>>T; while(T--) solve();
return 0;
}
D
#include <bits/stdc++.h>
//#define int long long
#define pb push_back
using namespace std;
const int N=(int)(5e5+5);
int n,a[N],b[N],ida[N],idb[N],prea[N],preb[N],cnta0[N],cnta1[N],cntb0[N],cntb1[N];
vector<int>veca[N],vecb[N];
void solve() {
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=1;i<=n;i++) cin>>b[i];
int tot=1,ans=0;
for(int i=1;i<=n;i++) ida[i]=1,idb[i]=1;
for(int i=29;i>=0;i--) {
bool ok=1;
for(int j=1;j<=n;j++) {
if((a[j]>>i)&1) {
++cnta1[ida[j]];
} else ++cnta0[ida[j]];
veca[ida[j]].pb(j);
}
for(int j=1;j<=n;j++) {
if((b[j]>>i)&1) ++cntb1[idb[j]];
else ++cntb0[idb[j]];
vecb[idb[j]].pb(j);
}
for(int j=1;j<=tot;j++) {
// cout<<cnta0[j]<<" "<<cn
if(cnta0[j]==cntb1[j]&&cnta1[j]==cntb0[j]){
} else ok=0;
}
for(int j=1;j<=n;j++) prea[j]=ida[j],preb[j]=idb[j];
if(ok) {
int pre=tot; ans+=(1<<i);
for(int j=1;j<=pre;j++) {
++tot; bool fl=0;
for(int x:veca[j]) {
if((a[x]>>i)&1) fl=1,ida[x]=tot;
}
for(int x:vecb[j]) {
if(!((b[x]>>i)&1)) fl=1,idb[x]=tot;
}
if(!fl) --tot;
else {
bool flll=0;
for(int x:veca[j]) {
if(!((a[x]>>i)&1)) flll=1;
}
for(int x:vecb[j]) {
if((b[x]>>i)&1) flll=1;
}
if(!flll) {
--tot;
for(int x:veca[j]) {
if((a[x]>>i)&1) ida[x]=j;
}
for(int x:vecb[j]) {
if(!((b[x]>>i)&1)) idb[x]=j;
}
}
}
}
}
for(int j=1;j<=n;j++) {
veca[prea[j]].clear(); vecb[preb[j]].clear();
cnta1[prea[j]]=cnta0[prea[j]]=0;
cntb1[preb[j]]=cntb0[preb[j]]=0;
}
}
cout<<ans<<'\n';
// for(int i=1;i<=tot;i++) veca[i].clear
}
signed main() {
cin.tie(0); ios::sync_with_stdio(false);
int T; cin>>T; while(T--) solve();
return 0;
}
E
暴力发现会 T,加速下当前第 \(i\) 然后要匹配 \(c\) 要跳到哪里就好了。
预处理的复杂度是线性的。
类失配树?
#include <bits/stdc++.h>
//#define int long long
#define pb push_back
using namespace std;
const int N=(int)(1e6+20);
char s[N],t[20];
int n,m,q,nex[N],NEX[N][26];
signed main() {
cin.tie(0); ios::sync_with_stdio(false);
cin>>s+1; n=strlen(s+1);
int kmpj=0;
for(int i=2;i<=n;i++) {
while(kmpj&&s[kmpj+1]!=s[i]) kmpj=nex[kmpj];
if(s[kmpj+1]==s[i]) ++kmpj;
nex[i]=kmpj;
}
for(int i=1;i<=n+10;i++) {
for(int j=0;j<26;j++) NEX[i][j]=-1;
}
for(int i=1;i<n;i++) {
for(int j=0;j<26;j++) {
int x=i;
while(1) {
if(s[x+1]==j+'a') {
NEX[i][j]=x; break ;
}
x=nex[x];
if(NEX[x][j]!=-1) {
NEX[i][j]=NEX[x][j]; break ;
}
}
if(NEX[i][j]==-1) NEX[i][j]=0;
}
}
int qwq=kmpj;
cin>>q;
while(q--) {
cin>>t+1; m=strlen(t+1);
int tot=n; kmpj=qwq;
for(int i=1;i<=m;i++) {
s[++tot]=t[i];
}
for(int i=n+1;i<=tot;i++) {
while(kmpj&&s[kmpj+1]!=s[i]) {
if(kmpj<n) {
kmpj=NEX[kmpj][s[i]-'a'];
} else kmpj=nex[kmpj];
}
if(s[kmpj+1]==s[i]) ++kmpj;
nex[i]=kmpj;
cout<<nex[i]<<' ';
}
cout<<'\n';
for(int i=n+1;i<=tot;i++) nex[i]=0,s[i]=0;
}
return 0;
}