Educational Codeforces Round 55 (Rated for Div. 2)

Posted shanxieng

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Educational Codeforces Round 55 (Rated for Div. 2)相关的知识,希望对你有一定的参考价值。

Educational Codeforces Round 55 (Rated for Div. 2)

链接

A Vasya and Book

傻逼题。。注意判边界。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<set>
#include<map>
#include<vector>
#include<cmath>
using namespace std;

typedef long long ll;

int t,n,x,y,d;

int main() {
    scanf("%d",&t);
    while(t--) {
        scanf("%d%d%d%d",&n,&x,&y,&d);
        int sxz=abs(x-y);
        if(sxz%d==0) {
            printf("%d
",sxz/d);
            continue;
        }
        int ans=0x7fffffff;
        if((y-1)%d==0)
            ans=min(ans,(x==1?0:(int)ceil((double)(x-1)/d))+(y-1)/d);
        if((n-y)%d==0)
            ans=min(ans,(x==n?0:(int)ceil((double)(n-x)/d))+(n-y)/d);
        if(ans==0x7fffffff) printf("-1
");
        else printf("%d
",ans);
    }
    return 0;
}

B Vova and Trophies

还是傻逼题。。还是要判好边界。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<set>
#include<map>
#include<vector>
#include<cmath>
using namespace std;

typedef long long ll;
const int Maxn=110000;

int n,a[Maxn],l[Maxn],ok[Maxn],tot;

char getach() {
    char ch=getchar();
    while(ch!=‘G‘&&ch!=‘S‘) ch=getchar();
    return ch;
}

int main() {
    scanf("%d",&n);
    for(int i=1;i<=n;i++) {
        if(getach()==‘G‘) {
            a[i]=1;
            if(i>2&&a[i-1]==0&&a[i-2])
                ok[tot]=1;
            l[tot]++;
        }
        else if(a[i-1]) tot++;
    }
    if(a[n]==1) tot++;
    if(tot==1) {
        printf("%d",l[0]);
        return 0;
    }
    int ans=0;
    for(int i=0;i<tot;i++) {
        ans=max(ans,l[i]+1);
        if(ok[i]) {
            if(tot==2)
                ans=max(ans,l[i]+l[i-1]);
            else ans=max(ans,l[i]+l[i-1]+1);
        }
    }
    printf("%d",ans);
    return 0;
}

C Multi-Subject Competition

开n个堆就好了,用队列存着目前堆非空且和不为负数的堆分别是那几个,时间复杂度(O(n log n))

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<set>
#include<map>
#include<vector>
#include<cmath>
using namespace std;

typedef long long ll;
const int Maxn=110000;

int n,m,c[Maxn],b[Maxn],ans,x,y,tot;

priority_queue<int> q[Maxn];

int main() {
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++) {
        scanf("%d%d",&x,&y);
        q[x].push(y);
    }
    for(int i=1;i<=m;i++)
        if(!q[i].empty()&&q[i].top()>0) {
            b[++tot]=q[i].top();
            c[tot]=i;
            q[i].pop();
        }
    int num=0;
    for(int i=1;i<=tot;i++)
        num+=b[i];
    ans=max(ans,num);
    while(tot) {
        int sxz=tot;
        tot=0;
        num=0;
        for(int i=1;i<=sxz;i++)
            if(!q[c[i]].empty()&&b[i]+q[c[i]].top()>0) {
                b[++tot]=b[i]+q[c[i]].top();
                c[tot]=c[i];
                q[c[i]].pop();
            }
        for(int i=1;i<=tot;i++)
            num+=b[i];
        ans=max(ans,num);
    }
    printf("%d",ans);
    return 0;
}

D Maximum Diameter Graph

这个题可以贪心,把所有的点按照度数限制排个序,然后枚举直径的长度,直径两边选度数限制最小的,其余的点选度数限制最大的,然后把其他的点挂上就好了。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<set>
#include<map>
#include<vector>
#include<cmath>
using namespace std;

typedef long long ll;
const int Maxn=110000;

int n,m,a[Maxn],b[Maxn];

int main() {
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]),b[i]=i;
    for(int i=1;i<=n;i++)
        for(int j=i+1;j<=n;j++)
            if(a[j]>a[i]) {
                swap(a[i],a[j]);
                swap(b[i],b[j]);
            }
    for(int i=n-2;i>=1;i--) {
        int num=0;
        for(int j=1;j<=i;j++)
            if(a[j]>=2) num+=a[j]-2;
            else {
                num=-1;
                break;
            }
        if(num>=n-i-2) {
            printf("YES %d
",i+1);
            printf("%d
",n-1);
            printf("%d %d
",b[n],b[1]);
            printf("%d %d
",b[n-1],b[i]);
            for(int j=1;j<i;j++) printf("%d %d
",b[j],b[j+1]);
            int temp=1;
            for(int j=i+1;j<=n-2;j++)
                if(a[temp]>2) {
                    a[temp]--;
                    printf("%d %d
",b[temp],b[j]);
                }
                else {
                    while(a[temp]==2) temp++;
                    a[temp]--;
                    printf("%d %d
",b[temp],b[j]);
                }
            return 0;
        }
    }
    puts("NO");
    return 0;
}

E Increasing Frequency

这道题是傻逼贪心,我竟然没看出来。。

大概就是记一下c出现个数的前缀和,然后枚举其他的每个数,把这个数在数列中出现的位置排个序,从前往后扫一遍,维护左右端点,然后对于一个区间,如果在这个区间中c的出现次数比这个数多,那就把这个区间扔掉。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;

typedef long long ll;
const int Maxn=510000;
const double eps=1e-9;

int n,c,x,a[Maxn],ans;

priority_queue<int,vector<int>,greater<int> >h[Maxn];

int main() {
//  freopen("test.in","r",stdin);
    scanf("%d%d",&n,&c);
    for(int i=1;i<=n;i++) {
        scanf("%d",&x);a[i]=a[i-1];
        if(x==c) a[i]++;
        h[x].push(i);
    }
    for(int i=1;i<=500000;i++)
        if(i!=c&&!h[i].empty()) {
            int sxz=0,zhy=1,last=h[i].top();
            h[i].pop();
            ans=max(ans,zhy);
            while(!h[i].empty()) {
                int temp=h[i].top();
                h[i].pop();
                sxz+=a[temp]-a[last];
                zhy++;
                if(sxz>=zhy) {
                    sxz=0;
                    zhy=1;
                }
                ans=max(ans,zhy-sxz);
                last=temp;
            }
        }
    printf("%d",ans+a[n]);
    return 0;
}

F

毒瘤。。。

G Petya and Graph

这个题是个傻逼网络流。。我竟然没看出来。

大概就是最小割建图,把每个点和每个边建点,每个边从他的两个端点连边,流量为正无穷;从原点向所有的点连边,流量为点的点权;从所有边向汇点连边,流量为边权。


    memset(b,0,sizeof(b));
    b[s]=1;
    while(!q.empty()) {
        int now=q.front();q.pop();
        for(int i=first[now];i;i=nxt[i])
            if(w[i]&&b[to[i]]==0) {
                b[to[i]]=b[now]+1;
                q.push(to[i]);
            }
    }
    return b[t];
}

ll dfs(int root,int flow) {
    if(root==t) return flow;
    for(int i=first[root];i;i=nxt[i])
        if(w[i]&&b[to[i]]==b[root]+1) {
            int temp=dfs(to[i],min(flow,w[i]));
            if(temp) {
                w[i]-=temp;
                w[i^1]+=temp;
                return temp;
            }
        }
    return 0;
}

ll dinic() {
    ll ans=0,temp;
    while(bfs())
        while(temp=dfs(s,inf))
            ans+=temp;
    return ans;
}

int main() {
//  freopen("test.in","r",stdin);
    scanf("%d%d",&n,&m);
    s=0,t=n+m+1;
    for(int i=1;i<=n;i++) {
        scanf("%I64d",&x);
        add(s,i,x);
    }
    for(int i=1,sxz=n+1;i<=m;i++,sxz++) {
        scanf("%d%d%I64d",&u,&v,&x);
        add(u,sxz,inf);
        add(v,sxz,inf);
        add(sxz,t,x);
        ans+=x;
    }
    printf("%I64d",ans-dinic());
    return 0;
}

以上是关于Educational Codeforces Round 55 (Rated for Div. 2)的主要内容,如果未能解决你的问题,请参考以下文章

Educational Codeforces Round 7 A

Educational Codeforces Round 7

Educational Codeforces Round 90

Educational Codeforces Round 33

Codeforces Educational Codeforces Round 54 题解

Educational Codeforces Round 27