Educational Codeforces Round 161 (Rated for Div. 2)(A-E)

Educational Codeforces Round 161 (Rated for Div. 2)(A-E)

A Tricky Template

分析

样例给的很强,读完做法就出来了。思考一下就是,如果有一个位置c[i]与a[i]和b[i]均不同,那么在此位置上就可以使用一个大写字母使得与c不匹配,而不会影响a和b,如果没有这样的位置,也就是说不管如何c[i]都会和前两个有一个重复,那么模板对应位置不管怎么放,都会对其中两个串产生相同的影响,因此与题目给定的要求是互斥的

代码

点击查看代码
void solve () {
    int n; cin >> n;
    string a, b, c; cin >> a >> b >> c;
    bool fl = false;
    for (int i = 0; i < n; i ++) {
    	if (a[i] != c[i] && b[i] != c[i]) fl = true;
    }
    if (fl) cout << "YES" << endl;
    else cout << "NO" << endl;
    return ;
}

B Forming Triangles

分析

因为边长都是2的幂次,我们知道\(2^{i - 1} + 2^{i - 1} = 2^{i}\),而三角形两边之和大于第三边,因此最长边起码有两条

代码

点击查看代码
ll calc1(ll x) {
	return x * (x - 1) / 2;
}

ll calc2(ll x) {
	return x * (x - 1) * (x - 2) / 6;
}

void solve () {
    int n; cin >> n;
    vector<int> a(n + 1);
	map<ll, int> mp;
    for (int i = 1; i <= n; i ++) {
    	cin >> a[i];
    	mp[a[i]] ++;
    }
    ll ans = 0, cn = 0;
    for (int i = 0; i <= n; i ++) {
    	ans += calc1(mp[i]) * cn + calc2(mp[i]);
    	cn += mp[i];
    }
    cout << ans << endl;
    return ;
}

C Closest Cities

分析

每次都是一定走到相邻的城市,前后缀和维护一下即可

代码

点击查看代码
void solve () {
    int n; cin >> n;
    vector<ll> a(n + 2);
    for (int i = 1; i <= n; i ++) cin >> a[i];
    a[0] = -INF;
    a[n + 1] = -a[0];
    vector<ll> pre(n + 2), suf(n + 2);
    for (int i = 1; i <= n; i ++) {
    	if (a[i] - a[i - 1] < a[i + 1] - a[i]) pre[i + 1] = pre[i] + a[i + 1] - a[i];
    	else pre[i + 1] = pre[i] + 1;
    }
    for (int i = n; i >= 1; i --) {
    	if (a[i] - a[i - 1] < a[i + 1] - a[i]) suf[i - 1] = suf[i] + 1;
    	else suf[i - 1] = suf[i] + a[i] - a[i - 1];
    }
    int m; cin >> m;
    while (m --) {
		int x, y; cin >> x >> y;
		if (x < y) cout << pre[y] - pre[x] << endl;
		else cout << suf[y] - suf[x] << endl;
    }
    return ;
}

D Berserk Monsters

分析

模拟即可

代码

点击查看代码
void solve () {
    int n; cin >> n;
    vector<int> a(n + 2), d(n + 2), l(n + 2), r(n + 2), alive;
    vector<bool> ok(n + 2);
    for (int i = 1; i <= n; i ++) cin >> a[i];
    for (int i = 1; i <= n; i ++) cin >> d[i];
    for (int i = 1; i <= n; i ++) l[i] = i - 1, r[i] = i + 1;
    for (int i = 1; i <= n; i ++) alive.pb(i), ok[i] = true;
    for (int i = 1; i <= n; i ++) {
    	set<int> death;
    	for (auto it : alive)
    		if (a[l[it]] + a[r[it]] > d[it]) 
    			death.insert(it);
    	alive.clear();
    	cout << death.size() << ' ';
    	for (auto it : death) ok[it] = false;
    	for (auto it : death) {
    		r[l[it]] = r[it];
    		l[r[it]] = l[it];
    		if (l[it] != 0 && ok[l[it]]) alive.pb(l[it]);
    		if (r[it] != n + 1 && ok[r[it]]) alive.pb(r[it]);
    	}
    }
    cout << endl;
    return ;
}

E Increasing Subsequences

分析

易知长度为i的递增序列包含的递增子序列个数为\(2 ^ {i}\),那么对于要求的x,我们首先从零开始放置,如0,1,2,3···直到这段递增序列包含的递增子序列数量刚好对应x二进制拆位中最大的1,然后从最高位1减一的位置反过来放,如0,1,2,3,4,5,3,2这样,其中0,1,2,3,4,5表示x的二进制位中最高位1为第六位,此时产生的总数为\(2 ^ 6\),此时从x的次高位1反过来遍历,第i位是1就放,放置之后可产生\(2 ^ i\)的贡献,而不会与后续逆序放置的数产生影响

代码

点击查看代码
void solve () {
    ll x; cin >> x;
    vector<int> ans;
    for (int i = 0; i < __lg(x); i ++)
    	ans.pb(i);
    for (int i = __lg(x) - 1; i >= 0; i --) {
    	if (x >> i & 1) 
    		ans.pb(i);
    }
    cout << ans.size() << endl;
    for (auto a : ans)
    	cout << a << ' ';
    cout << endl;
    return ;
}
posted @ 2024-01-27 14:56  ComistryMo  阅读(20)  评论(0)    收藏  举报