Codeforces Round #340 (Div. 2) (617A,617B,617C,617D(Constructive ),617E(莫队算法))

本文详细介绍了如何解决Codeforces平台上的四个编程问题:'大象行走'、'巧克力分割'、'浇水花卉'和'多边形路径'。通过优化算法和逻辑思考,为每个问题提供了有效的解题思路及AC代码,旨在帮助编程爱好者提高解决问题的能力。

比赛的时候由于入了一道题的坑,而且一直没爬出来。。。

Elephant

题目连接:

http://codeforces.com/contest/617/problem/A

解题思路:

It's optimal to do the biggest possible step everytime. So elephant should do several steps by distance 5 and one or zero step by smaller distance. Answer equals to 

AC代码:

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;

int main(){
    int x;
    scanf("%d",&x);
    if(x%5)
        printf("%d\n",x/5+1);
    else
        printf("%d\n",x/5);
    return 0;
}

Chocolate

题目连接:

http://codeforces.com/contest/617/problem/B

解题思路:

We are given array which contains only ones and zeroes. We must divide it on parts with only one 1.

Tricky case: when array contains only zeroes answer equals to 0.

In general. Between two adjacent ones we must have only one separation. So, answer equals to product of values posi - posi - 1 whereposi is position of i-th one.

弱英语差,没看到这句话:You are asked to calculate the number of ways he can do it. 

AC代码:

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;

typedef long long ll;
int a[110];

int main(){
    int n;
    while(~scanf("%d",&n)){
        for(int i = 0; i < n; i++)
            scanf("%d",&a[i]);
        int i;
        for(i = 0; i < n; i++){
            if(a[i] == 1)
                break;
        }
        if(i == n){
            printf("0\n");
            continue;
        }
        ll cnt = 1,ans = 1;
        for(; i < n; i++){
            if(a[i] == 1){
                ans *= cnt;
                cnt = 1;
            }
            else
                cnt++;
        }
        printf("%lld\n",ans);
    }
    return 0;
}


Watering Flowers

题目连接:

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

解题思路:

First radius equals to zero or distance from first fountain to some flower. Let's iterate over this numbers. Second radius equals to maximal distance from second fountain to flower which doesn't belong to circle with first radius. Now we should choose variant with minimalr12 + r22.

AC代码(n^2):

#include <iostream>
#include <vector>
#define INF 1e18
using namespace std;

typedef long long ll;

ll square(int x){
    return (ll)x * x;
}

int main() {
    ios_base::sync_with_stdio(false); cin.tie(0);

    int n, x1, y1, x2, y2;
    while(cin >> n >> x1 >> y1 >> x2 >> y2){
        vector<pair<ll, ll> > dist(n);
        for (int i = 0; i < n; i++) {
            int x, y;
            cin >> x >> y;
            dist[i].first = square(x - x1) + square(y - y1);
            dist[i].second = square(x - x2) + square(y - y2);
        }
        dist.push_back({0, 0});

        ll result = INF;
        for(int i = 0; i <= n; i++){
            ll r1 = dist[i].first;
            ll r2 = 0;
            for(int j = 0; j <= n; j++){
                if(dist[j].first > r1){
                    r2 = max(r2, dist[j].second);
                }
            }
            result = min(result, r1 + r2);
        }
        cout << result << endl;
    }
    return 0;
}

AC代码(nlogn):

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

typedef long long ll;

ll square(int x) {
    return x * (ll) x;
}

int main() {
    ios_base::sync_with_stdio(false); cin.tie(0);

    int n, x1, y1, x2, y2;
    while(cin >> n >> x1 >> y1 >> x2 >> y2){
        vector< pair<ll, ll> > dist(n);
        for (int i = 0; i < n; i++) {
            int x, y;
            cin >> x >> y;
            dist[i].first = square(x - x1) + square(y - y1);
            dist[i].second = square(x - x2) + square(y - y2);
        }

        sort(dist.begin(), dist.end());
        vector<ll> maxsuf(n + 1);
        for (int i = n - 1; i >= 0; i--) {
            maxsuf[i] = max(maxsuf[i + 1], dist[i].second);
        }

        ll result = min(dist[n - 1].first, maxsuf[0]);
        for (int i = 0; i < n; i++) {
            ll r1 = dist[i].first;
            ll r2 = maxsuf[i + 1];
            result = min(result, r1 + r2);
        }
        cout << result << endl;
    }
    return 0;
}

Polyline

题目连接:

http://codeforces.com/contest/617/problem/D

解题思路:

Answer equals to one if all coordinates x or y of points are same.

When answer equals to two? Let's iterate over all pairs of points. Let first point in pair is beginning of polyline, second point is end. Only one or two such polylines with answer two exist. If third point is on the polyline it belongs to rectangle with corners in first two points. We can just check it.

Else answer equals to three. We can build vertical lines which contains the most left and the most right point and horizontal line through third point. If we erase some excess rays we will get polyline.

AC代码:

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;

int x[3], y[3];

bool is_between(int a, int b, int c) {
    return min(a, b) <= c && c <= max(a, b);
}

bool judge(int i, int j, int k) {
    return (x[k] == x[i] || x[k] == x[j]) && is_between(y[i], y[j], y[k]) ||
           (y[k] == y[i] || y[k] == y[j]) && is_between(x[i], x[j], x[k]);
}

int main(){
    for(int i = 0; i < 3; i++)
        scanf("%d%d",&x[i],&y[i]);

    if(x[0] == x[1] && x[1] == x[2] || y[0] == y[1] && y[1] == y[2]){
        puts("1");
    }else if(judge(0,1,2) || judge(0,2,1) || judge(1,2,0)){
        puts("2");
    }else{
        puts("3");
    }
    return 0;
}


XOR and Favorite Number

题目连接:

http://codeforces.com/contest/617/problem/E

解题思路:

We have array a.

Let's calculate array pref (pref[0] = 0).

Xor of subarray a[l...r] equals to .

So query (l, r) is counting number of pairs ij (l - 1 ≤ i < j ≤ r.

Let we know answer for query (l, r) and know for all v cnt[v] — count of v in a[l - 1...r]. We can update in O(1) answer and cnt if we move left or right border of query on 1. So we can solve problem offline in  with sqrt-decomposion (Mo's algorithm).

AC代码:

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;

typedef long long ll;
const int blocks = 300;

struct Query{
	int l, r, id;
	bool operator < (const Query& other) const{
		return l / blocks < other.l / blocks || (l / blocks == other.l / blocks && r < other.r);
	}
};

int n, m, k;
Query q[100000];
ll ans[100000];
int s[100001];
int cnt[1 << 20];
ll cur;

void add(int x){
	cur += cnt[x ^ k];
	cnt[x]++;
}

void del(int x){
	cnt[x]--;
	cur -= cnt[x ^ k];
}

int main(){
    while(~scanf("%d%d%d",&n,&m,&k)){
        for (int i = 1; i <= n; i++){
            scanf("%d", &s[i]);
            s[i] ^= s[i - 1];
        }
        for (int i = 0; i < m; ++i){
            scanf("%d%d",&q[i].l,&q[i].r);
            q[i].id = i;
        }
        sort(q,q+m);
        int l = 1, r = 0;
        for(int i = 0; i < m; ++i){
            while(q[i].l - 1 > l)
                del(s[l++]);
            while(q[i].l - 1 < l)
                add(s[--l]);
            while(q[i].r > r)
                add(s[++r]);
            while(q[i].r < r)
                del(s[r--]);
            ans[q[i].id] = cur;
        }
        for (int i = 0; i < m; ++i){
            printf("%lld\n", ans[i]);
        }
    }
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值