Educational Codeforces Round 25A-G题解

来源:互联网 发布:lol遇到网络问题 编辑:程序博客网 时间:2024/06/04 19:56

A:水题遇到0就输出每个0前面就几个0然后最后末尾一个0没有输出

#include<iostream> #include<cstdio>#include<cstring>using namespace std;typedef long long int ll;char s[100];int a[300];int ans[300];int main(){    int n;    scanf("%d",&n);    scanf("%s",s);    memset(a,0,sizeof(a));    for(int i = 0; i < n; i++)        a[i] = s[i]-'0';    int len = 0;    for(int i = 0; i <= n; i++){        if(a[i]){            len++;        }        else{            cout<<len;            len = 0;        }    }     cout<<endl;    return 0;}

B:枚举每个点放下x看能不能连成5个以后即可

#include<iostream>#include<cstring>#include<algorithm>using namespace std;char map[15][15];int x_move[4] = {1,0,1,1};int y_move[4] = {-1,-1,1,0};bool judge(int x,int y){    return x>=0&&y>=0&&x<10&&y<10&&map[x][y] == 'X';}bool check(int x,int y){    for(int i = 0; i < 4; i++){        int tx = x+x_move[i],ty = y+y_move[i];        int len = 1;        while(judge(tx,ty)){            len++;            tx+=x_move[i];            ty+=y_move[i];        }        tx = x-x_move[i],ty = y-y_move[i];        while(judge(tx,ty)){            len++;            tx-=x_move[i];            ty-=y_move[i];         }        if(len>=5)            return 1;    }    return 0;}int main(){    memset(map,0,sizeof(map));    for(int i = 0; i < 10; i++)        scanf("%s",map[i]);    int ok = 0;    for(int i = 0; i < 10; i++)        for(int j = 0; j < 10; j++)            if(map[i][j] == '.')                if(check(i,j))                    ok = 1;    ok?puts("YES"):puts("NO");    return 0;}

C:把困难从小到大排序后用k*2一个一个扫过去取max(k*2,a[i]*2),如果不够那就把k乘2每乘一次答案就+1乘到k足够

#include<iostream>#include<cstring>#include<algorithm>#include<cstdio>using namespace std;typedef long long int ll;int a[10005];int n,k;int main(){    cin>>n>>k;    for(int i = 0; i < n; i++)        cin>>a[i];    sort(a,a+n);    k*=2;    int ans = 0;    for(int i = 0; i < n; i++){        while(k<a[i]){            ans++;            k*=2;        }         k = max(k,a[i]*2);    }    cout<<ans<<endl;    return 0;}

D题:先求s字符串里面有多少个a,b。。。。z字母并且统计’?’的个数,把t字符串循环扫过去如果对应的字母还有就把对应的字母的个数减一如果没有就把’?’改成t对应的字母,如果再没有’?’就结束了把’?’全部放满了

#include<iostream>#include<cstdio>#include<algorithm>#include<cstring>using namespace std;const int mx = 1e6+5;char s[mx],t[mx];int a[mx];int vis[30];int main(){    scanf("%s%s",s,t);    int n = strlen(s);    int m = strlen(t);    int len = 0;    for(int i = 0; i < n; i++)        if(s[i]=='?')            a[len++] = i;        else            vis[s[i]-'a']++;    int j = 0,i = 0;    for(j = 0; vis[t[j]-'a']||i<len;  j=(j+1)%m){        if(vis[t[j]-'a'])            vis[t[j]-'a']--;        else            s[a[i++]] = t[j];    }    cout<<s<<endl;    return 0;}

E:标签从n-1设置过去每次设置集合中(出度为0的最大结点)设置为对应的数值n,n-1….1,然后把这个结点从图中删除掉,如果还有新的结点出度为0把它加进出度为0的集合里面,重复上面操作

#include<iostream>#include<cstdio>#include<algorithm>#include<cstring>#include<set>#include<vector>using namespace std;const int mx = 1e5+5;vector<int>g[mx];int ans[mx];int n,m;int in[mx];set<int>st;int main(){    scanf("%d%d",&n,&m);    for(int i = 0; i < m; i++){        int u,v;        scanf("%d%d",&u,&v);        g[v].push_back(u);        in[u]++;    }    for(int i = 1; i <= n; i++) if(!in[i]) st.insert(-i);    int j = n;    while(!st.empty()){        int u = -*(st.begin());        st.erase(*st.begin());        ans[u] = j--;        for(int i = 0; i < g[u].size(); i++){            int v = g[u][i];            in[v]--;            if(!in[v])  st.insert(-v);         }    }     for(int i = 1; i <= n; i++)        printf("%d%c",ans[i],i == n?'\n':' ');}

F:先跑一遍从每个字符开始的kmp记录下来,然后动态规划求
从第j个字符到第i个字符循环节如果能够整除就是
dp[i] = min(dp[i],dp[j-1]+d+bit[len/d]);不能就是
dp[i] = min(dp[i],dp[j-1]+1+len);

#include<iostream>#include<cstring>#include<cstdio>#include<algorithm>using namespace std;const int mx = 8005;const int inf = 0x3f3f3f3f;int f[mx][mx];char s[mx];int bit[mx];int n;int dp[mx];void getfail(int x){    int i = x,j = x-1;     f[x][x] = x-1;    while(i<=n){        while(j!=x-1 && s[i] != s[j]) j = f[x][j];        f[x][++i] = ++j;    } }int main(){    scanf("%s",s+1);    n = strlen(s+1);    int k = 10,b = 1;    for(int i = 0; i <= 8000; i++){        if(i/k>0){            bit[i] = ++b;            k*=10;        }        else            bit[i] = b;    }    for(int i = 1; i <= n; i++)        getfail(i);    dp[0] = 0;    for(int i = 1; i <= n; i++){        dp[i] = dp[i-1]+2;  /*这个不能等于i+1的原因是因为可能前面是循环节  然后会比较短我下面如果1到i不是循环节我下面  会算一下但是这个就不会算坑死了在这里 */        for(int j = i-1; j >= 1; j--){            int fail = f[j][i+1]-1;            int d = i-fail;            int len = i-j+1;            if(len%d)                dp[i] = min(dp[i],dp[j-1]+1+len);            else                dp[i] = min(dp[i],dp[j-1]+d+bit[len/d]);        }    }    printf("%d\n",dp[n]);    return 0;}

G:将一个被涂黑节点设置成为头节点,然后每个节点设置到这个节点的路径上最小的节点为ans[i]然后如果还有涂黑就取黑中间的最小节点
然后查询求答案就是min(ans[x],黑节点最小的答案)。

#include<iostream>#include<cstdio>#include<vector>#include<cstring>#include<algorithm>using namespace std;const int mx = 1e6+5;vector<int>g[mx];int ans[mx];void dfs(int u,int fa){    for(int i = 0; i < g[u].size(); i++){        int v = g[u][i];        if(v!=fa){            ans[v] = min(v,ans[u]);            dfs(v,u);        }    }}int main(){    int n,m,q,last = 0,z,t,x,minn;    scanf("%d%d",&n,&q);    for(int i = 1; i < n; i++){        int u,v;        scanf("%d%d",&u,&v);        g[u].push_back(v);        g[v].push_back(u);    }    q--;    scanf("%d%d",&t,&z);    x = (last+z)%n+1;    ans[x] = x;    dfs(x,-1);     minn = x;    while(q--){        scanf("%d%d",&t,&z);        x = (last+z)%n+1;        if(t==2)    printf("%d\n",last = min(ans[x],minn));        else minn = min(minn,ans[x]);    }    return 0;}
原创粉丝点击