Codeforces Round #656 (Div. 3) D E 题解

D题:
思路:一开始我们会去选择字母a放在左边还是右边,然后会再去选择字母b放在左边或者右边,一直这样循环下去直到只剩下一个字母。那么每次面临的选择就是2次,总共会是2^k=n,则我们可以直接用深搜去解决这道题,并且先用前缀和去预处理出每个区间的每个字母的数量。
代码:

#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;
    }
}

E题:
思路:一开始先将这些边都存起来,在输入边的时候,若为有向边,则直接将边加入到图中,并且记录每个点的入度。然后我们可以用队列优化的拓扑去求出拓扑序,若在求拓扑的过程中发现环,则输出NO。为什么要求拓扑序呢?因为入度大的点的拓扑序越大,我们的策略是将那些无向边指向两个点中入度大的点,这样就可以保证不会形成环。
代码:

#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);
                }
            }
        }
    }
}

猜你喜欢

转载自blog.csdn.net/weixin_45755679/article/details/107425086