1. 程式人生 > >Educational Codeforces Round 55 (Rated for Div. 2)

Educational Codeforces Round 55 (Rated for Div. 2)

sizeof force () codeforce sub ova == break eof

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\n",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\n");
        else printf("%d\n",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\n",i+1);
            printf("%d\n",n-1);
            printf("%d %d\n",b[n],b[1]);
            printf("%d %d\n",b[n-1],b[i]);
            for(int j=1;j<i;j++) printf("%d %d\n",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\n",b[temp],b[j]);
                }
                else {
                    while(a[temp]==2) temp++;
                    a[temp]--;
                    printf("%d %d\n",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)