专栏文章

题解:CF1271F Divide The Students

CF1271F题解参与者 1已保存评论 0

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
0 条
当前快照
1 份
快照标识符
@mioxd6b4
此快照首次捕获于
2025/12/03 02:42
3 个月前
此快照最后确认于
2025/12/03 02:42
3 个月前
查看原文
提供一种好写的线性做法。
注意到单个和全部是好做的,而两个可以转化为全局加单点减同一个数,于是转化为前两者。枚举总共加的值,计算出所有第二类的取值范围相加检查即可,时间复杂度 O(n)O(n)
对边界略加分讨应该可以做到 O(1)O(1)
O(n)O(n) 实现。
CPP
#include<bits/stdc++.h>
using namespace std;

int l[3],r[3],s[8],P[8]={0,7,3,5,1,6,2,4},a[8],L[8],R[8];
void print(int k){
	int res=k;
	for(int i=0;i<3;i++) res-=L[i];
	for(int i=0;i<3;i++){
		res-=(a[(1<<i)^7]=min(res,R[i]-L[i]));
		a[(1<<i)^7]+=L[i];
		a[1<<i]=max(0,l[i]-k+a[(1<<i)^7]);
	}
	a[7]=res;
	for(int i=1;i<8;i++) printf("%d ",a[P[i]]);printf("\n");
}
inline void solve(){
	int sum=0;
	for(int i=0;i<3;i++) scanf("%d",&r[i]);
	for(int i=0;i<3;i++) scanf("%d",&l[i]);
	for(int i=1;i<8;i++) scanf("%d",&s[P[i]]),sum+=(__builtin_popcount(P[i])>1)*s[P[i]];
	for(int i=0;i<3;i++){
		int sum=0;
		for(int j=(1<<i);j<8;j=((j+1)|(1<<i))) sum+=s[j];
		l[i]=max(0,sum-l[i]);
		if(l[i]>r[i]) return puts("-1"),void(); 
	}
	for(int i=0;i<=sum;i++){
		int fl=1,suml=0,sumr=s[7];
		for(int j=0;j<3;j++){
			L[j]=max(0,-(r[j]-i)),R[j]=min(s[(1<<j)^7],s[1<<j]-(l[j]-i));
			if(L[j]>R[j]) fl=0;
			suml+=L[j],sumr+=R[j];
		}
		fl&=(suml<=i&&i<=sumr);
		if(!fl) continue;
		return print(i);
	}
	puts("-1");
}
signed main(){
	signed T=1;
	scanf("%d",&T);
	while(T--) solve();
	return 0;
}

评论

0 条评论,欢迎与作者交流。

正在加载评论...