題解-ARC126


https://atcoder.jp/contests/arc126

A - Make 10

總共有 \([2,2,3,3],[3,3,4],[2,4,4],[2,2,2,4],[2,2,2,2,2]\) 五種拼法,顯然如果按照一種拼法拼了就會一直接着按這種拼法,所以我們給這5種拼法一個優先級,按順序依次執行即可。

#include<bits/stdc++.h>
typedef long long ll;
ll zsy[3],d[5][3]={{2,2,0},{0,2,1},{1,0,2},{3,0,1},{5,0,0}};
int p[5];
int main(){
	int T;
	scanf("%d",&T);
	while(T--){
		ll a,b,c,ans=0;
		scanf("%lld%lld%lld",&a,&b,&c);
		for(int i=0;i<5;i++)p[i]=i;
		do{
			ll nowans=0;
			zsy[0]=a,zsy[1]=b,zsy[2]=c;
			for(int i=0;i<5;i++){
				int x=p[i];
				ll now=1e15;
				for(int j=0;j<3;j++)
					if(d[x][j]!=0)now=std::min(now,zsy[j]/d[x][j]);
				for(int j=0;j<3;j++)
					zsy[j]-=now*d[x][j];
				nowans+=now;
			}
			ans=std::max(ans,nowans);
		}while(std::next_permutation(p,p+5));
		printf("%lld\n",ans);
	}
	return 0;
}

B - Cross-free Matching

注意到最后取法按 a 排序后不存在逆序對,所以我們不妨直接按 a 排序求 lis,要求相同的 a 不能取到,於是相同的 a 的 b 從大到小排即可。

#include<bits/stdc++.h>
typedef long long ll;
struct node{
	int a,b;
	friend bool operator<(node x,node y){return x.a==y.a?x.b>y.b:x.a<y.a;}
}p[200005];
int n,m;
int c[200005],f[200005],ans;
void add(int x,int v){
	while(x<=n){
		c[x]=std::max(c[x],v);
		x+=x&-x; 
	}
}
int ask(int x){
	int ret=0;
	while(x){
		ret=std::max(ret,c[x]);
		x-=x&-x;
	}
	return ret;
}
int main(){
	n=read();m=read();
	for(int i=1;i<=m;i++)
		p[i].a=read(),p[i].b=read();
	std::sort(p+1,p+1+m);
	for(int i=1;i<=m;i++)
		f[i]=std::max(1,ask(p[i].b-1)+1),add(p[i].b,f[i]),ans=std::max(ans,f[i]);
	printf("%d\n",ans);
	return 0;
}

C - Maximize GCD

對於一個極大 d 滿足所有數都是他的倍數那么他就是 gcd。考慮枚舉gcd=d計算需要幾步,其實就是 \((d-a_i\bmod d)\bmod d\),一開始我以為有單調性於是就寫了個二分,但其實這顯然沒有單調性。但也只是在 \(\max A\) 以內沒有,於是我們考慮對小於 \(\max A\) 的數特殊處理,顯然可以枚舉倍數計算 \(a_i\bmod d\),於是就 \(\max A \ln \max A\) 了。

#include<bits/stdc++.h>
typedef long long ll;
int N;
ll zsy[600005],K,ans,s1[600005],s2[600005];
bool check(ll d){
	ll ret=0;
	for(int i=1;i<=N;i++){
		ret+=(d-zsy[i]%d)%d;
		if(ret>K)return 0;
	}
	return 1;
}
int main(){
	scanf("%d%lld",&N,&K);
	for(int i=1;i<=N;i++)scanf("%lld",zsy+i),s1[zsy[i]]+=zsy[i],s2[zsy[i]]+=1;
	std::sort(zsy+1,zsy+1+N);
	for(int i=1;i<=600000;i++)s1[i]+=s1[i-1],s2[i]+=s2[i-1];
	for(int i=1;i<=300000;i++){
		ll now=0;
		for(int j=0;j<=300000;j+=i){
			// [j+1,j+i-1] 
			now+=(s2[j+i-1]-s2[j])*(j+i)-(s1[j+i-1]-s1[j]);
			if(now>K)break;
		}
		if(now<=K){
			ans=i;
		}
	}
	ll l=zsy[N]+1,r=2e18;
	while(l<=r){
		ll mid=(l+r)>>1;
		if(check(mid)){
			ans=std::max(ans,mid);
			l=mid+1;
		}else{
			r=mid-1;
		}
	}
	printf("%lld\n",ans);
	return 0;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM