Codeforces Round 886 (Div. 4)(D~G)

还是div4做着有意思哈哈哈

D. Balanced Round

目录

D. Balanced Round

E. Cardboard for Pictures

F. We Were Both Children

G. The Morning Star

H. The Third Letter


D. Balanced Round

题意:有 n 个问题,问题 i 的难度是a[i],进行下面两个操作:
1. 从列表中删除一些问题 (可以是 0 个)
2. 将剩下的问题按任意顺序重新排列。
当且仅当任意两个连续问题的难度绝对值最多相差 k 时,一轮比赛才算平衡,为了使问题的排列平衡,你至少要删除多少个问题?

思路:如何排列可以使得结果最优呢?我们发现:当按照难度进行排序的时间,满足 "任意两个连续问题的难度绝对值最多相差 k " 的最长子段的长度会最大,然后,将其余的问题删除即可。

参考代码:

#include 

using i64 = long long;

void solve() {
    int n, k;
    cin >> n >> k;
    vector a(n);
    for (int i = 0; i < n; i++) {
        cin >> a[i];
    }
    sort(a.begin(), a.end());
    int cnt = 1, ans = 1;
    for (int i = 1; i < n; i++) {
        if (a[i] - a[i - 1] <= k) {
            cnt++;
        } else {
            cnt = 1;
        }
        ans = max(ans, cnt);
    }
    cout << n - ans << "\n";
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int t;
    cin >> t;
    while (t--) {
        solve();
    }
    return 0;
}

E. Cardboard for Pictures

题意:有 n 副成正方形的画,给定每幅画中一正方形阴影部分的边长 s[i] ,每幅画的边长是其中阴影部分的边长加上 2×w ,给你这 n 副画的面积之和 c ,求 w 的值。

思路:显然,答案 w 具有二分性质,为了防止越界,在每次检查答案合法性时,当 sum>c 时,跳出循环即可。

参考代码:

#include
using namespace std;
using ll = long long;
ll a[1100000];
ll check(ll mid,ll n,ll c)
{
    ll sum=0;
    for(ll i=1;i<=n;i++)
    {
        sum+=(2*mid+a[i])*(2*mid+a[i]);
        if(sum>c) break;
    }
    return sum;
}
void solve()
{
    ll n,c;cin>>n>>c;
    for(ll i=1;i<=n;i++)
    {
        cin>>a[i];
    }
    ll l=0,r=1e9;
    ll mid;
    while(l+1!=r)
    {
        mid=(l+r)>>1;
        if(check(mid,n,c)>c) r=mid;
        else if(check(mid,n,c)==c)
        {
            l=mid;
            break;
        }
        else l=mid;
    }
    cout<>t;
    while(t--)
        solve();
    return 0;
}

F. We Were Both Children

题意:在坐标原点有 n 只青蛙,每隔一秒,它们会向同一方向分别跳动 a[i] 的长度,可以任意在坐标 1∼n 中选择一个坐标放上陷阱,问怎样设计陷阱,可以使得跳到陷阱上的青蛙数量最多。

思路:枚举每一个 ≤n 的 a[i] 的倍数即可。

参考代码:

#include
using namespace std;
#define int long long
int t,n,a[200010],dp[200010],ans=0;
//dp只是预处理数组而已,没什么别的含义...
int getans(int x){
	int sum=0;
	for(int i=1;i*i<=x;i++){
		if(x%i==0){
			if(i*i==x) sum+=dp[i];
			else sum+=dp[i],sum+=dp[x/i];
		}
	}
	return sum;
}
signed main(){
	cin>>t;
	while(t--){
		memset(dp,0,sizeof(dp));
		ans=0;
		cin>>n;
		for(int i=1;i<=n;i++) cin>>a[i];
        //预处理
		for(int i=1;i<=n;i++) if(a[i]<=n) dp[a[i]]++;
		for(int i=1;i<=n;i++) ans=max(ans,getans(i));
		cout<

G. The Morning Star

思路:假设同方向的点的个数是 x,那么罗盘有 x 个可以选择的点,晨星有 x−1 个可以选择的点,即该方向对答案的贡献为 x*(x−1) ,我们统计四个方向分别有多少点,把其贡献累加起来即可。

参考代码:

#include
using namespace std;
using ll = long long;
const ll ma = 200005;
mapmp[4];
void solve()
{
	for (int i = 0; i < 4; ++i)
		mp[i].clear();
	int n;
	scanf("%d", &n);
	ll ans = 0;
	for (int i = 1; i <= n; ++i)
	{
		int x, y;
		scanf("%d%d", &x, &y);
		ans += mp[0][x]++;
		ans += mp[1][y]++;
		ans += mp[2][x - y]++;
		ans += mp[3][x + y]++;
	}
	printf("%lld\n", 2 * ans);
}
int main()
{
	ll t;cin>>t;
	while(t--) solve();
}

H. The Third Letter

题意:为了赢得最艰苦的战斗,米尔恰为他的军队想出了一个好策略。他有 n个士兵,并决定以某种方式将他们安排在营地里。每个士兵都必须属于一个营地,在 x 轴上的每个整数点都有一个营地。该策略由 m个限制条件组成。条件 i 表明士兵u 与士兵 v 距离 w , w 可正可负,即具有方向性。现在,米尔恰想知道是否存在满足所有条件的士兵分区方案。

思路:考察了带权并查集模板。

参考代码:

你可能感兴趣的:(CF比赛(练习),c++,数据结构,算法)