Educational Codeforces Round 22 题解

来源:互联网 发布:网络安全技术有哪几类 编辑:程序博客网 时间:2024/06/05 20:13

比赛链接:http://codeforces.com/contest/813

A. The Contest

题目比较长,读懂后,模拟即可。

#include <bits/stdc++.h>using namespace std;const int maxn = 1010;int n, m, x, l, r, sum;int main(){    while(~scanf("%d",&n)){        sum=0;        for(int i=0; i<n; i++){            scanf("%d",&x);            sum+=x;        }        scanf("%d",&m);        int ans = 0;        bool flag = 0;        for(int i=0; i<m; i++){            scanf("%d%d",&l,&r);            if(flag) continue;            if(l>=sum&&r>=sum){                ans = l;                flag = 1;            }            else if(r>=sum&&l<sum){                ans = sum;                flag = 1;            }        }        if(flag==1) printf("%d\n", ans);        else printf("-1\n");    }    return 0;}

B. The Golden Age

枚举暴力

#include <bits/stdc++.h>using namespace std;typedef long long LL;LL x,y,l,r;LL mul(LL x, LL y){    if(double(x)*(double)y>=1e18) return r+1;    return x*y;}vector <LL> v;int main(){    while(~scanf("%lld%lld%lld%lld", &x,&y,&l,&r))    {        v.clear();        for(LL i=1; i<=r; i=mul(i,x)){            for(LL j=1; i+j<=r; j=mul(j,y)){                if(l<=i+j){                    v.push_back(i+j);                }            }        }        v.push_back(l-1);        v.push_back(r+1);        sort(v.begin(), v.end());        LL ans = 0;        for(int i=0; i<v.size()-1; i++){            ans = max(ans, v[i+1]-v[i]-1);        }        printf("%lld\n", ans);    }    return 0;}

C. The Tag Game

题意:给你一个无向有根树,根节点为1,有两个人,A在节点1,B在节点X,AB轮流走,B先走,每次可以原地不动或是向相邻节点移动一次。A想最快抓到B,B想最慢被抓到,问什么时候A抓到B。
解法:

#include <bits/stdc++.h>using namespace std;const int maxn = 2e6+7;vector <int> v[maxn];int n, x, dep[maxn], ans;void dfs1(int u, int pa, int d){    dep[u] = d;    for(int son : v[u]){        if(son == pa) continue;        dfs1(son, u, d+1);    }}int maxdep;void dfs2(int u, int pa){    if(dep[u]<=maxdep) return;    ans = max(ans, dep[u]);    for(int son : v[u]){        if(son == pa) continue;        dfs2(son, u);    }}int main(){    scanf("%d %d", &n, &x);    for(int i=1; i<n; i++){        int x, y;        scanf("%d %d", &x, &y);        v[x].push_back(y);        v[y].push_back(x);    }    dfs1(1,1,0);    ans = 0;    maxdep = dep[x]/2;    dfs2(x,x);    printf("%d\n", ans<<1);    return 0;}

D. Two Melodies

题意:求两个不相交的子集长度之和最大是多少,能放入同一子集的条件是首先顺序不能变,然后每一个相邻的要么相差1或者相差7的倍数。

这里写图片描述

#include <bits/stdc++.h>using namespace std;const int maxn = 5010;int n,a[maxn],dp[maxn][maxn],maxmod[8],maxnum[100010];int main(){    while(~scanf("%d", &n)){        for(int i=1; i<=n; i++) scanf("%d", &a[i]);        memset(dp, 0, sizeof(dp));        int ans = 0;        for(int i=0;i<=n; i++){            memset(maxnum,0,sizeof(maxnum));            memset(maxmod,0,sizeof(maxmod));            for(int j=1; j<=i; j++){                maxmod[a[j]%7] = max(maxmod[a[j]%7], dp[i][j]);                maxnum[a[j]] = max(maxnum[a[j]], dp[i][j]);            }            for(int j=i+1; j<=n; j++){                dp[i][j] = max(dp[i][j], dp[i][0]+1);                dp[i][j] = max(dp[i][j], maxmod[a[j]%7]+1);                dp[i][j] = max(dp[i][j], maxnum[a[j]-1]+1);                //dp[i][j] = max(dp[i][j], maxnum[a[j]]+1);                dp[i][j] = max(dp[i][j], maxnum[a[j]+1]+1);                maxmod[a[j]%7] = max(maxmod[a[j]%7], dp[i][j]);                maxnum[a[j]] = max(maxnum[a[j]], dp[i][j]);                dp[j][i] = dp[i][j];                ans = max(ans, dp[i][j]);            }        }        printf("%d\n", ans);    }    return 0;}

E. Army Creation

题意:n个数a[i],q次询问,n,a[i],q<=1e5。每次问[l,r]内最多可以选多少个数,满足同一个数的出现次数不超过k?

解法:设b[i] 从i开始数k个和a[i]相同的数的位置,不存在设为n+1。则[l,r] 只要b[i]>r的数都能可以被选上,转化为求区间[l,r]内有多少个数>=r。题目要求在线 所以套用主席树 ,建立权值线段树,前缀i内,第[l,r]大的数有多少个,ans=前缀r内[r,inf]个数-前缀i-1内[r,inf]个数 。

#include <bits/stdc++.h>using namespace std;const int maxn = 100010;int n, q, k, a[maxn], b[maxn];vector <int> pos[maxn];struct node{    int l,r,sum;}T[maxn*40];void pre_deal(){    for(int i=n; i>=1; i--){        int sz = pos[a[i]].size();        if(sz < k) b[i] = n+1;        else b[i] = pos[a[i]][sz-k];        pos[a[i]].push_back(i);    }}int cnt, root[maxn];int build(int l, int r){    int rt = ++cnt;    T[rt].sum = 0, T[rt].l = T[rt].r = 0;    if(l == r) return rt;    int mid = (l+r)/2;    T[rt].l = build(l, mid);    T[rt].r = build(mid+1, r);    return rt;}void update(int l, int r, int &x, int y, int pos){    T[++cnt] = T[y], T[cnt].sum++, x = cnt;    if(l == r) return;    int mid = (l+r)/2;    if(pos <= mid) update(l, mid, T[x].l, T[y].l, pos);    else update(mid+1, r, T[x].r, T[y].r, pos);}int query(int l, int r, int c, int L, int R){    if(L <= l && r <= R) return T[c].sum;    int mid = (l+r)/2, ans=0;    if(L <= mid) ans += query(l, mid, T[c].l, L, R);    if(mid < R) ans += query(mid+1, r, T[c].r, L, R);    return ans;}int main(){    while(~scanf("%d %d", &n,&k)){        for(int i=1; i<=n; i++) scanf("%d", &a[i]);        pre_deal();        cnt = 0;        root[0] = build(1, n+1);        for(int i=1; i<=n; i++) update(1, n+1, root[i], root[i-1], b[i]);        scanf("%d", &q);        int l, r, last = 0;        while(q--){            scanf("%d %d", &l, &r);            l = (l+last)%n+1;            r = (r+last)%n+1;            if(l > r) swap(l, r);            int ans = query(1, n+1, root[r], r+1, 2e5) - query(1, n+1, root[l-1], r+1, 2e5);            printf("%d\n", ans);            last = ans;        }        return 0;    }}

F. Bipartite Checking

蒟蒻不会啊,暂时补不了。QAQ

原创粉丝点击