Codeforces Round #613 (Div. 2)解题报告

比赛页面


A


简单题

#include <bits/stdc++.h>

using namespace std;

#define ll long long
ll input(){
	ll x=0,f=0;char ch=getchar();
	while(ch<'0'||ch>'9') f|=ch=='-',ch=getchar();
	while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
	return f? -x:x;
}

int n;
string s;

int main(){
	n=input();
	cin>>s;
	cout<<n+1;
}

B


最长连续子串板子题,写个最长连续子串就OK了。但是要注意特判最长连续子串是否是整个串。

#include <bits/stdc++.h>

using namespace std;

#define ll long long
ll input(){
	ll x=0,f=0;char ch=getchar();
	while(ch<'0'||ch>'9') f|=ch=='-',ch=getchar();
	while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
	return f? -x:x;
}

const int N=1e5+7;

int n;
ll a[N];

int main(){
	int T=input();
	while(T--){
		n=input();
		ll sum=0;
		for(int i=1;i<=n;i++){
			a[i]=input();
			sum+=a[i];
		}
		ll res=0,dp=0,len=0,rlen=0;
    	for(int i=1;i<=n;i++){
	        if(dp+a[i]<=0) dp=0,len=0;
	        else dp+=a[i],len++;
	        if(res<dp||(res==dp&&len<rlen))
	        	res=dp,rlen=len;
   		}
   		// cout<<sum<<" "<<res<<" "<<rlen<<endl;
   		if(sum>res){
			printf("YES
");
		}else if(rlen==n&&a[n]!=0&&a[1]!=0) printf("YES
");
		else printf("NO
");
	}
}

C


不难想到用(sqrt{n})的时间来枚举因子,用(log n)的时间来判定因子是否互质。总复杂度(O(sqrt{n}log n))

#include <bits/stdc++.h>

using namespace std;

#define ll long long
ll input(){
	ll x=0,f=0;char ch=getchar();
	while(ch<'0'||ch>'9') f|=ch=='-',ch=getchar();
	while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
	return f? -x:x;
}

ll x;
ll a,b;

int main(){
	x=input();
	for(ll i=1;i*i<=x;i++){
		if(x%i==0){
			if(__gcd(i,x/i)==1){
				a=i,b=x/i;
			}
		}
	}
	printf("%lld %lld
",a,b);
}

D


对所有的数的二进制建立一棵0/1tire树,然后贪心dfs就好了。对于答案来说,如果所有的数的某一位如果全为1就填1,对于全为0就填0,如果即存在1的情况又存在0的情况就这一位填0还是1两种情况都找一下,最后取最小答案就好。

#include <bits/stdc++.h>

using namespace std;

#define ll long long
ll input(){
	ll x=0,f=0;char ch=getchar();
	while(ch<'0'||ch>'9') f|=ch=='-',ch=getchar();
	while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
	return f? -x:x;
}

const int N=1e5+7;

int t[N*30][2],cnt,Ans=1<<30;

void dfs(int rt,int dep,int val){
	if(dep<0){
		Ans=min(Ans,val);
		return;
	}
	if(t[rt][0]&&t[rt][1])
		dfs(t[rt][0],dep-1,val|(1<<dep)),
		dfs(t[rt][1],dep-1,val|(1<<dep));
	else if(t[rt][1]) dfs(t[rt][1],dep-1,val);
	else dfs(t[rt][0],dep-1,val);
}

int main(){
	int n=input();
	for(int i=1;i<=n;i++){
		int x=input();
		int rt=0;
		for(int j=30;~j;j--){
			bool tmp= x>>j&1;
			if(!t[rt][tmp])
				t[rt][tmp]=++cnt;
			rt=t[rt][tmp];
		}
	}
	dfs(0,30,0);
	printf("%d
",Ans);
}

E


首先避免离散化后求答案可能会导致冲突,把所有的(l)(r)都乘(2),然后把(l-1,l,l+1,r-1,r,r+1)都加入离散化数组中,离散化后,维护一个前缀和数组。我们知道如果删掉某一段可能会对答案产生贡献,唯一可能就是前缀和数组中为1的段,因此我们给这些全为1的段做一个标记,最后求答案时只要统计区间内有多少个标记就可以了,因此我们也可以通过前缀和维护标记的数量,但是要注意段的两端可能会出现减少答案的情况。最后还要考虑,所有段都不相交的情况。

#include <bits/stdc++.h>

using namespace std;

#define ll long long
ll input(){
	ll x=0,f=0;char ch=getchar();
	while(ch<'0'||ch>'9') f|=ch=='-',ch=getchar();
	while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
	return f? -x:x;
}

vector <ll> v;

int getid(ll x){
	return lower_bound(v.begin(),v.end(),x)-v.begin()+1;
}

const int N=2e5+7;

#define PII pair<ll,ll>
#define fr first
#define sc second
#define mp make_pair

int T;
int n;
PII a[N];
int b[N*8],add[N*8],sum[N*8];

int main(){
	T=input();
	while(T--){
		n=input();
		for(int i=1;i<=n;i++){
			a[i].fr=input()*2;
			a[i].sc=input()*2;
			v.push_back(a[i].fr-1);
			v.push_back(a[i].fr+1);
			v.push_back(a[i].fr);
			v.push_back(a[i].sc+1);
			v.push_back(a[i].sc);
			v.push_back(a[i].sc-1);
		}

		sort(v.begin(),v.end());
		v.erase(unique(v.begin(),v.end()),v.end());
		int cnt=v.size();
		for(int i=0;i<=cnt;i++){
			b[i]=add[i]=sum[i]=0;
		}

		for(int i=1;i<=n;i++){
			a[i].fr=getid(a[i].fr),a[i].sc=getid(a[i].sc);
			add[a[i].fr]++;
			add[a[i].sc+1]--;
		}

		int tmp=0;
		for(int i=1;i<=cnt;i++){
			tmp+=add[i];
			b[i]=tmp;
		}

		for(int i=1;i<=cnt;i++){
			if(b[i]==1&&b[i-1]!=1) sum[i]=sum[i-1]+1;
			else sum[i]=sum[i-1];
			// cout<<sum[i]<<endl;
		}

		int bas=0;
		for(int i=1;i<=cnt;i++){
			if(b[i]==0&&b[i-1]!=0) bas++;
		}
		// cout<<":"<<bas<<endl;
		int Ans=bas-1;
		for(int i=1;i<=n;i++){
			tmp=sum[a[i].sc]-sum[a[i].fr-1];
			if(b[a[i].fr-1]==0&&b[a[i].fr]==1) tmp--;
			if(b[a[i].sc+1]==0&&b[a[i].sc]==1) tmp--;
			// cout<<tmp<<endl;
			Ans=max(Ans,tmp+bas);
		}
		printf("%d
",Ans);
		v.clear();
	}
}
原文地址:https://www.cnblogs.com/-aether/p/12202249.html