• Codeforces Round #551 (Div. 2)


    A:签到,很多人O(n)容易被hack,不如写O(nt)

    #include<bits/stdc++.h>
    using namespace std;
    int n,t,ans,mn,s,d;
    int main()
    {
        scanf("%d%d",&n,&t);
        mn=1e9;
        for(int i=1;i<=n;i++)
        {
            scanf("%d%d",&s,&d);
            while(s<t)s+=d;
            if(s<mn)mn=s,ans=i;
        }
        printf("%d",ans);
    }
    View Code

    B:签到,写起来贼麻烦,对每行/列按照高度排序,然后填当前高度,水平不行写了好长时间才过

    #include<bits/stdc++.h>
    using namespace std;
    const int N=107;
    struct node{int id,tp,h;}c[N*2];
    int n,m,h,num,a[N],b[N],has[N][N],mp[N][N],vis1[N],vis2[N];
    vector<int>G1,G2;
    bool cmp(node a,node b){return a.h>b.h;}
    int main()
    {
        scanf("%d%d%d",&n,&m,&h);
        for(int i=1;i<=m;i++)scanf("%d",&a[i]),c[++num]=(node){i,0,a[i]};
        for(int i=1;i<=n;i++)scanf("%d",&b[i]),c[++num]=(node){i,1,b[i]};
        for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
        scanf("%d",&has[i][j]);
        sort(c+1,c+num+1,cmp);
        for(int i=100,p=0;i>=1;i--)
        {
            G1.clear(),G2.clear();
            while(p<num&&c[p+1].h==i)
            {
                p++;
                if(!c[p].tp)G1.push_back(c[p].id),vis1[c[p].id]=1;
                else G2.push_back(c[p].id),vis2[c[p].id]=1;
            }
            for(int j=0;j<G1.size();j++)
            for(int k=1;k<=n;k++)
            if(vis2[k]&&has[k][G1[j]])mp[k][G1[j]]=i;
            for(int j=0;j<G2.size();j++)
            for(int k=1;k<=m;k++)
            if(vis1[k]&&has[G2[j]][k])mp[G2[j]][k]=i;
        }
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m;j++)printf("%d ",mp[i][j]);
            puts("");
        }
    }
    View Code

    C:签到,显然就是把第一位"("和第n位")"去掉,剩下的仍然满足是个括号序列,然后贪心求解

    #include<bits/stdc++.h>
    using namespace std;
    const int N=3e5+7;
    int n,now,n1,n2;
    char s[N];
    int main()
    {
        scanf("%d",&n);
        scanf("%s",s+1);
        if(n&1){puts(":(");return 0;}
        if(s[1]==')'||s[n]=='('){puts(":(");return 0;}
        if(n==2){puts("()");return 0;}
        s[1]='(',s[n]=')';
        for(int i=1;i<=n;i++)if(s[i]=='(')n1++;else if(s[i]==')')n2++;
        if(n1>n/2||n2>n/2){puts(":(");return 0;}
        n1=n/2-n1,n2=n/2-n2;
        for(int i=2;i<n;i++)
        {
            if(s[i]=='(')now++;
            else if(s[i]==')')now--;
            else if(n1)s[i]='(',now++,n1--;
            else s[i]=')',now--,n2--;
            if(now<0){puts(":(");return 0;}
        }
        for(int i=1;i<=n;i++)printf("%c",s[i]);
    }
    View Code

    D:很容易想到树形DP,f[i]表示以i为根的子树中,根节点i的最大值,sum[i]表示以i为根的子树中叶节点的个数。然后如果a[i]=1,则f[i]=sum[i]-min{sum[son]-f[son]},反之则f[i]=1+Σ(f[son]-1)

    #include<bits/stdc++.h>
    using namespace std;
    const int N=3e5+7;
    int n,m,a[N],f[N],sum[N],fa[N];
    vector<int>G[N];
    void dfs(int u)
    {
        if(!G[u].size()){sum[u]=1,f[u]=1;return;}
        for(int i=0;i<G[u].size();i++)dfs(G[u][i]),sum[u]+=sum[G[u][i]];
        if(a[u])
        {
            int mn=1e9+7;
            for(int i=0;i<G[u].size();i++)mn=min(mn,sum[G[u][i]]-f[G[u][i]]);
            f[u]=sum[u]-mn;
        }
        else{
            int mx=0;
            for(int i=0;i<G[u].size();i++)mx+=f[G[u][i]]-1;
            f[u]=mx+1;
        }
    }
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)scanf("%d",&a[i]);
        for(int i=2;i<=n;i++)scanf("%d",&fa[i]),G[fa[i]].push_back(i);
        dfs(1);
        printf("%d",f[1]);
    }
    View Code

    E:交互题,很容易发现:如果一个框框内答案为奇数,其中必然有且仅有一个头/尾,反之则有0或2个。由于头尾不在一个格子里,可以考虑这样的做法:先询问每一整行,再询问每一整列。发现存在两种情况:1、头尾的行列均不同。2、头尾的行列有一个相同。如果是情况1,则会问出2行和2列答案是奇数,这样再询问4次即可知道答案。如果是情况2,假设在同一行,则问出2列答案是奇数,行答案全是偶数。这时候可以单独询问其中一列,对行进行二分询问。询问次数就是2n+4或者2n+logn

    #include<bits/stdc++.h>
    using namespace std;
    int n,nr,nc,R[3],C[3],mp[3][3];
    int main()
    {
        scanf("%d",&n);
        for(int i=1,x;i<=n;i++)
        {
            printf("? %d 1 %d %d
    ",i,i,n),fflush(stdout);
            scanf("%d",&x);
            if(x&1)R[++nr]=i;
        }
        for(int i=1,x;i<=n;i++)
        {
            printf("? 1 %d %d %d
    ",i,n,i),fflush(stdout);
            scanf("%d",&x);
            if(x&1)C[++nc]=i;
        }
        if(nr&&nc)
        {
            for(int i=1;i<=2;i++)
            for(int j=1,x;j<=2;j++)
            {
                printf("? %d %d %d %d
    ",R[i],C[j],R[i],C[j]),fflush(stdout);
                scanf("%d",&x);
                if(x&1)mp[i][j]=1;
            }
            printf("!");
            for(int i=1;i<=2;i++)
            for(int j=1;j<=2;j++)
            if(mp[i][j])printf(" %d %d",R[i],C[j]);
            return 0;
        }
        if(nr)
        {
            int l=1,r=n,mid,x;
            while(l<r)
            {
                mid=(l+r)/2;
                printf("? %d %d %d %d
    ",R[1],l,R[1],mid),fflush(stdout);
                scanf("%d",&x);
                if(x&1)r=mid;else l=mid+1;
            }
            printf("! %d %d %d %d",R[1],l,R[2],l);
            return 0;
        }
        if(nc)
        {
            int l=1,r=n,mid,x;
            while(l<r)
            {
                mid=(l+r)/2;
                printf("? %d %d %d %d
    ",l,C[1],mid,C[1]),fflush(stdout);
                scanf("%d",&x);
                if(x&1)r=mid;else l=mid+1;
            }
            printf("! %d %d %d %d",l,C[1],l,C[2]);
            return 0;
        }
    }
    View Code

    F:一句话题意:长为l的线段,每次等概率选出2点,选出n条线段,求至少被k条线段覆盖的长度期望

    出题人你能不能把题目写得简洁明了些?考场上我看到自闭还没看懂直接弃疗了。

    很显然l是个作废的条件,只需要求长为1的然后将ans*=l即可。

    每个端点概率相互独立,所以期望被分成2n+1段,每段期望长度为l/(2n+1),然后仅需DP出期望覆盖几段即可。然后给2n个点匹配即可。f[i][j]表示前i个点,j个左端点没匹配上,然后就暴力转移一波即可。

    #include<bits/stdc++.h>
    using namespace std;
    const int N=2019,mod=998244353;
    int n,m,ans,f[N<<1][N],g[N<<1][N];
    int qpow(int a,int b)
    {
        int ret=1;
        while(b)
        {
            if(b&1)ret=1ll*ret*a%mod;
            a=1ll*a*a%mod,b>>=1;
        }
        return ret;
    }
    int main()
    {
        scanf("%d%d%d",&n,&m,&ans);
        f[0][0]=1;
        for(int i=1;i<=2*n;i++)
        for(int j=0;j<=min(i,n);j++)
        {
            if(!j)f[i][j]=f[i-1][j+1],g[i][j]=g[i-1][j+1];
            else f[i][j]=(f[i-1][j-1]+1ll*(j+1)*f[i-1][j+1])%mod,g[i][j]=(g[i-1][j-1]+1ll*(j+1)*g[i-1][j+1])%mod;
            if(j>=m)g[i][j]=(f[i][j]+g[i][j])%mod;
        }
        ans=1ll*ans*qpow(1ll*f[2*n][0]*(2*n+1)%mod,mod-2)%mod*g[2*n][0]%mod;
        printf("%d",ans);
    }
    View Code

    小号(hfctf0210):rank17 rating+=129 now_rating=2210(和大号最高rating一样,这是巧合还是天注定?!)

  • 相关阅读:
    类名+函数名(参数1,参数2.....){.......return this;}
    报错!无法从静态上下文中引用非静态 变量
    ERROR无法从静态上下文中引用非静态变量
    字符编码笔记:ASCII,Unicode和UTF-8
    MySQL其他类型常用函数
    MySQL流程函数
    MySQL日期和时间函数
    MySQL数值函数
    MySQL字符串函数
    MySQL位运算符优先级
  • 原文地址:https://www.cnblogs.com/hfctf0210/p/10703896.html
Copyright © 2020-2023  润新知