Codeforces Round #670 (Div. 2)

A
http://codeforces.com/contest/1406/problem/A
桶排个序,记录一下个数,然后从小到大扫两遍,每次直到个数为零的那个数,将他们加起来即可。

#include <bits/stdc++.h>
using namespace std;
int T,ans,n,i,GG,f[200],a[200];
 
int main(){
	cin >>T;
	while (T--){
		ans=0;
		cin >>n;
		memset(f,0,sizeof(f));
		for (i=1; i<=n; i++){
			cin >>a[i];
			f[a[i]]++;
		}
		for (i=0,GG=0; !GG; i++){
			if (f[i]){f[i]--; continue;}
			if (!f[i]) ans+=i,GG=1;
		}
		for (i=0,GG=0; !GG; i++){
			if (f[i]){f[i]--; continue;}
			if (!f[i]) ans+=i,GG=1;
		}
		cout <<ans <<"\n";
	}
}

B
http://codeforces.com/contest/1406/problem/B
选的数比较少,我先把读入的数组按正负分成两组,分别算出他们选 1,2,…,5 个数乘起来的最值,然后组合判断一下,选最优的就行了。注意一下可能出现0.

#include <bits/stdc++.h>
using namespace std;
int T,n,cnt1,cnt2,cnt3,tmp;
long long a1[100005],a2[100005],b1[100005],b2[100005],b3[100005],ans;

bool cmp(int x,int y){return x>y;}

int main(){
	cin >>T;
	while (T--){
		memset(a1,0,sizeof(a1));
		memset(a2,0,sizeof(a2));
		cin >>n;
		cnt1=cnt2=cnt3=0;
		for (int i=1,tmp; i<=n; i++){
			cin >>tmp;
			if (tmp<0) a1[++cnt1]=tmp;
			if (tmp>0) a2[++cnt2]=tmp;
			if (tmp==0) cnt3++;
		}
		if (cnt3>n-5){
			cout <<"0\n";
			continue;
		}
		sort(a1+1,a1+cnt1+1,cmp);
		sort(a2+1,a2+cnt2+1,cmp);
		b1[0]=b2[0]=b3[0]=1;
		for (int i=1; i<=5; i++) if (i<=cnt1) b1[i]=b1[i-1]*a1[i];
		for (int i=cnt1,k=1; k<=5 && i; i--,k++) b3[k]=b3[k-1]*a1[i];
		b2[0]=1;
		for (int i=1; i<=5; i++) if (i<=cnt2) b2[i]=b2[i-1]*a2[i];
		ans=-300000000000000000ll;
		if (cnt3) ans=0;
		for (int i=0; i<=5; i++) if (cnt1>=i && cnt2>=5-i){
			ans=max(ans,b1[i]*b2[5-i]);
			ans=max(ans,b3[i]*b2[5-i]);
		}
		cout <<ans <<"\n";
	}
}

C
http://codeforces.com/contest/1406/problem/C

D
http://codeforces.com/contest/1406/problem/D
答案满足二分单调条件,先二分答案。
模拟一下过程,会发现b,c数组最优情况和 a 数组的相邻差值有关,比如从左往右排,那么c[1]选二分的m肯定最优,之后能算出b[1],再根据 a[2] 与 a[1] 的大小关系选择 c[2]继承c[1] 还是 b[2]继承b[1],(可以想像,相邻两位中bc至少其中一项相同,是更优的),一直到最右边,判断一下 b[n] 是否大于 m 即可。
但题目还有区间修改的维护要求,我开始想的是用树状数组维护,但是会超时。
后来再想想,发现其实可以把差值按正负分开求和,分别加到b[1]和c[1]上,得到的结果就是b[n]和c[n]了,这样check()的时候就是 O1 的了,于是问题解决。
在这里插入图片描述
看图可能更清除一点。(数据是我下面程序中末端注释中那一组)

#include <cstdio>
#define M ((l+r)>>1)
#define lowbit(x) (x&(-x))
long long n,L,R,X,q,sb,sc,ll,rr,a[100005];
long long ans;

int check(long long x){
	if ((ll-x+sb)>x) return 0;
	return 1;
}

void ef(long long l,long long r){
	if (l==r){
		ans=l;
		return;
	}
	if (check(M)){
		ef(l,M);
		return;
	}
	ef(M+1,r);
}

int main(){
	scanf("%lld",&n);
	for (int i=1; i<=n; i++) scanf("%lld",&a[i]);
	for (int i=1; i<n; i++){
		if (a[i+1]>a[i]) sb+=a[i+1]-a[i];
		else sc+=a[i+1]-a[i];
	}
	ll=a[1],rr=a[n];
	for (int i=1; i<n; i++) a[i]=a[i+1]-a[i];
	//for (int i=1; i<=n; i++) S.Add(i,i,a[i]);
	ef(-10000000000000000ll,10000000000000000ll);
	printf("%lld\n",ans);
	
	scanf("%lld",&q);
	while (q--){
		scanf("%lld%lld%lld",&L,&R,&X);
		if (L==1) ll+=X;
		
		if ((L-1)>0) (a[L-1]>0) ? sb-=a[L-1] : sc-=a[L-1];
		if (R<n) (a[R]>0) ? sb-=a[R] : sc-=a[R];
		
		if (L-1>0) a[L-1]+=X;
		if (R<n) a[R]-=X;
		
		if ((L-1)>0) (a[L-1]>0) ? sb+=a[L-1] : sc+=a[L-1];
		if (R<n) (a[R]>0) ? sb+=a[R] : sc+=a[R];
		
		ef(-10000000000000000ll,10000000000000000ll);
		printf("%lld\n",ans);
	}
}

/*
4
-3 6 -2 -8 
3
1 3 -4
3 3 5
3 3 -4

*/

E
http://codeforces.com/contest/1406/problem/E
发现这样一个东西:
一组询问
B p
A p
就可以知道x是不是p的倍数。
那么有两种思路:
一种是直接从2往后询问,边问边把后面不符合的删掉,时间复杂度好像挺高
另一种是把 n 里面的质数先问了,再将得出为 x 因数的质数拿出来乘方询问,得到它们的幂,感觉一下似乎复杂度是够的。(不过程序还没写出来 LOL

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值