Educational Codeforces Round 134 [Rated for Div. 2] | CF1721

第一次 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 个必要条件就能充分了。

  1. \(a_i\le b_j\)

  2. \(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

image

#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;
} 

F

posted @ 2022-08-28 18:11  FxorG  阅读(150)  评论(0)    收藏  举报