【暴力搜索】【莫队算法】【贪心】[Codeforces Round #340 (Div. 2) ]题解报告

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/JeremyGJY/article/details/50582725

A. Elephant

http://codeforces.com/contest/617/problem/A
完全就是贪心的裸题可以很容易的发现要走尽量多的步数才能走到最接近n的地方,然后判断是不是刚好走到n就行了

#include <cstdio>
int main(){
    int n;
    scanf("%d", &n);
    printf("%d\n", n/5+int(n%5>0));

    return 0;
}

B. Chocolate

http://codeforces.com/contest/617/problem/B
可以发现对于每一块巧克力至少有1个,那么每一次多出1个坚果那么就有之前那么多个空位可以选择,乘上(空位数量+1)就好了,在这里注意特判全部都是0的情况和记得开long long

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std;
const int MAXN = 100;
int s[MAXN+10];
int main(){
    int n, sum=0;
    scanf("%d", &n);
    for(int i=1;i<=n;i++)
        scanf("%d", &s[i]), sum+=s[i];
    if(!sum){
        printf("0\n");
        return 0;
    }
    int l = 1;
    while(!s[l]) l++;
    long long cnt=1, counter=1;
    for(int i=l;i<=n;i++){
        if(s[i]==0) counter++;
        else{
            cnt *= counter;
            counter = 1LL;
        }
    printf("%I64d\n", cnt);

    return 0;
}

C. Watering Flowers

http://codeforces.com/contest/617/problem/C
以第一个圆心枚举半径然后判断到第二个圆心的最远的不属于第一个圆心的点的距离,住注意特殊处理第一个圆心半径为0的情况,同时记得开个long long

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std;
const int MAXN = 2000;
long long s[MAXN+10][2];
long long PF(long long u){return u*u;}
int main(){
    long long n, x1, x2, y1, y2;
    scanf("%I64d%I64d%I64d%I64d%I64d", &n, &x1, &y1, &x2, &y2);
    long long ans = 0x7fffffffffffffff;
    for(long long i=1;i<=n;i++)
        scanf("%I64d%I64d", &s[i][0], &s[i][1]);
    s[0][0] = x1, s[0][1] = y1;
    for(long long i=0;i<=n;i++){
        long long tmp = PF(s[i][0]-x1)+PF(s[i][1]-y1);
        long long t2 = 0;
        for(int j=1;j<=n;j++)
            if(PF(s[j][0]-x1)+PF(s[j][1]-y1) > tmp)
                t2 = max(t2, PF(s[j][0]-x2) + PF(s[j][1]-y2));
        ans = min(ans, t2+tmp);
    }
    printf("%I64d\n", ans);

    return 0;
}

D. Polyline

http://codeforces.com/contest/617/problem/D
可以通过观察发现答案其实只有1 2 3三种情况那么首先可以发现如果任意两个点在同一条直线上并且另一个点做该直线的垂线的交点在两个点的两边的延长线上(包括端点)那么之需要1次转向,否则就需要3次,1次就只有一种情况——三个点在同一条直线上

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int check(int x1, int y1, int x2, int y2){
    return x1 == x2 || y1 == y2;
}
int main(){
    int x1, x2, x3;
    int y1, y2, y3;
    scanf("%d%d", &x1, &y1);
    scanf("%d%d", &x2, &y2);
    scanf("%d%d", &x3, &y3);
    if(check(x1, y1, x2, y2) && check(x1, y1, x3, y3) && check(x2, y2, x3, y3)) printf("1\n");
    else{
        int ans = 3;
        if(check(x1, y1, x2, y2)){
            if(x1 == x2 && (y3 >= max(y1, y2) || y3 <= min(y1, y2)))
                ans = 2;
            if(y1 == y2 && (x3 <= min(x1, x2) || x3 >= max(x1, x2)))
                ans = 2;
        }
        if(check(x1, y1, x3, y3)){
            if(x1 == x3 && (y2 >= max(y1, y3) || y2 <= min(y1, y3)))
                ans = 2;
            if(y1 == y3 && (x2 <= min(x1, x3) || x2 >= max(x1, x3)))
                ans = 2;
        }
        if(check(x2, y2, x3, y3)){
            if(x3 == x2 && (y1 >= max(y3, y2) || y1 <= min(y3, y2)))
                ans = 2;
            if(y3 == y2 && (x1 <= min(x3, x2) || x1 >= max(x3, x2)))
                ans = 2;
        }
        printf("%d\n", ans);
    }

    return 0;
}

E. XOR and Favorite Number

http://codeforces.com/contest/617/problem/E
莫队算法的题目,具体内容可以参考莫队算法的论文,首先可以知道k=sum[a]^sum[b-1]因为这里sum[a]^sum[b-1]其实就是b-a之间的xor的值了那么每一次寻找有没有匹配的sum,左端点就找对应的右边的sum值得个数。

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <cmath>
using namespace std;
const int MAXS = 2000000;
const int MAXN = 100000;
int val[MAXN+10], sum[MAXN+10];
long long t2[MAXS+10], t1[MAXS+10];
struct Task{
    int l, r;
    int lid, id;
    long long ans;
}Q[MAXN+10];
bool cmp(const Task &a, const Task &b) {
    if(a.lid == b.lid)
        return a.r < b.r;
    return a.lid < b.lid;
}
bool cmp2(const Task &a, const Task &b) {
    return a.id < b.id;
}
int main(){
    int n, m, k;
    scanf("%d%d%d", &n, &m, &k);
    for(int i=1;i<=n;i++) scanf("%d", &val[i]);
    sum[1] = val[1];
    for(int i=2;i<=n;i++) sum[i] = sum[i-1] ^ val[i];
    int _bit = sqrt(n + 0.5);
    for(int i=1;i<=m;i++)
        scanf("%d%d", &Q[i].l, &Q[i].r), Q[i].lid=(Q[i].l-1)/_bit+1,Q[i].id=i;
    sort(Q+1, Q+1+m, cmp);
    int l=1, r=0;
    long long tmp=0;
    for(int i=1;i<=m;i++){
        while(l < Q[i].l){
            tmp -= t2[k^sum[l-1]];
            t1[sum[l-1]]--;
            t2[sum[l]]--;
            l++;
        }
        while(l > Q[i].l){
            l--;
            t1[sum[l-1]]++;
            t2[sum[l]]++;
            tmp += t2[k^sum[l-1]];
        }
        while(r < Q[i].r){
            r++;
            t1[sum[r-1]]++;
            t2[sum[r]]++;
            tmp += t1[k^sum[r]];
        }
        while(r > Q[i].r){
            tmp -= t1[k^sum[r]];
            t1[sum[r-1]]--;
            t2[sum[r]]--;
            r--;
        }
        Q[i].ans = tmp;
    }
    sort(Q+1, Q+1+m, cmp2);
    for(int i=1;i<=m;i++)
        printf("%I64d\n", Q[i].ans);

    return 0;
}
展开阅读全文

没有更多推荐了,返回首页