Codeforces Round #656 (Div. 3) DE solution

Question D:
Idea: At first, we will choose whether the letter a is placed on the left or the right, and then we will choose the letter b to be placed on the left or the right, and the cycle continues until only one letter remains. Then the choice is 2 times each time, the total will be 2^k=n, then we can directly use the deep search to solve this problem, and first use the prefix and to preprocess the number of each letter in each interval .
Code:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<vector>
#include<stack>
using namespace std;
typedef long long ll;
const int MAXN=1e6+5;
const int M=1e6+5;
const double eps=1e-7;
const ll INF=0x3f3f3f3f;
char s[MAXN];
int sum[30][MAXN];
int ans;
void dfs(int l,int r,char c,int cnt)
{
    
    
    if(l==r)
    {
    
    
        if(s[l]==c) ans=min(ans,cnt);
        else ans=min(ans,cnt+1);
        return;
    }
    dfs(l,(l+r)/2,c+1,cnt+r-(l+r)/2-sum[c-'a'+1][r]+sum[c-'a'+1][(l+r)/2]);
    dfs((l+r)/2+1,r,c+1,cnt+(l+r)/2-l+1-sum[c-'a'+1][(l+r)/2]+sum[c-'a'+1][l-1]);
}
int main()
{
    
    
    int t;
    cin>>t;
    while(t--)
    {
    
    
        int n;
        cin>>n;
        cin>>s+1;
        for(int i=1;i<=26;i++)
        {
    
    
            sum[i][0]=0;
        }
        for(int i=1;i<=n;i++)
        {
    
    
            for(int j=1;j<=26;j++)
            {
    
    
                sum[j][i]=sum[j][i-1];
            }
            int k=s[i]-'a'+1;
            sum[k][i]++;
        }
        ans=1e9;
        dfs(1,n,'a',0);
        cout<<ans<<endl;
    }
}

Question E:
Idea: At the beginning, save these edges first. When inputting edges, if they are directed edges, add the edges directly to the graph and record the in-degree of each point. Then we can use the queue-optimized topology to find the topological order. If a ring is found during the topological finding, NO will be output. Why is topological order required? Because the topological order of a point with a large in-degree is greater, our strategy is to point those undirected edges to the point with a large in-degree in the two points, so as to ensure that no ring is formed.
Code:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<vector>
#include<stack>
using namespace std;
typedef long long ll;
const int MAXN=2e5+5;
const double eps=1e-7;
const ll INF=0x3f3f3f3f;
int n,m;
int cnt=0;
int head[MAXN];
int pos[MAXN];
int in[MAXN];
struct  EDGE
{
    
    
    int to;
    int next;
}e[MAXN];
struct node
{
    
    
    int a,b;
    int val;
}f[MAXN];
void add(int u,int v)
{
    
    
    e[cnt].to=v;
    e[cnt].next=head[u];
    head[u]=cnt++;
}
int toposort()
{
    
    
    queue<int>q;
    int res=n;
    int tot=0;
    for(int i=1;i<=n;i++)
    {
    
    
        if(in[i]==0) {
    
    q.push(i);res--;pos[i]=++tot;}
    }
    while(!q.empty())
    {
    
    
        int u=q.front();
        q.pop();
        in[u]--;
        for(int i=head[u];i!=-1;i=e[i].next)
        {
    
    
            int v=e[i].to;
            in[v]--;
            if(in[v]==0) {
    
    q.push(v);res--;pos[v]=++tot;}
        }
    }
    if(res==0) return 1;
    else return -1;
}
int main()
{
    
    
    int t;
    scanf("%d",&t);
    while(t--)
    {
    
    
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
        {
    
    
            head[i]=-1;
            pos[i]=0;
            in[i]=0;
        }
        cnt=0;
        int u,v,w;
        for(int i=1;i<=m;i++)
        {
    
    
            scanf("%d%d%d",&f[i].val,&f[i].a,&f[i].b);
            if(f[i].val==1) {
    
    add(f[i].a,f[i].b);in[f[i].b]++;}
        }
        int kk=toposort();
        if(kk==-1)
        {
    
    
            printf("NO\n");
        }
        else
        {
    
    
            printf("YES\n");
            for(int i=1;i<=m;i++)
            {
    
    
                if(f[i].val==1) printf("%d %d\n",f[i].a,f[i].b);
                else
                {
    
    
                    if(pos[f[i].a]<pos[f[i].b]) printf("%d %d\n",f[i].a,f[i].b);
                    else printf("%d %d\n",f[i].b,f[i].a);
                }
            }
        }
    }
}

Guess you like

Origin blog.csdn.net/weixin_45755679/article/details/107425086