zoukankan      html  css  js  c++  java
  • Codeforces Round #648 (Div. 2) 简要题解

    A

    每一次操作会消去一个没被占用的行和一个没被占用的列,取个min之后判奇偶性即可。

    int n,m;
    bool vis1[110],vis2[110];
    
    int main()
    {
        int T=read();
        while (T--)
        {
            n=read();m=read();
            rep(i,1,n) vis1[i]=0;
            rep(i,1,m) vis2[i]=0;
            int c1=n,c2=m;
            rep(i,1,n)
            {
                rep(j,1,m)
                {
                    int x=read();
                    if (!x) continue;
                    if (!vis1[i]) {vis1[i]=1;c1--;}
                    if (!vis2[j]) {vis2[j]=1;c2--;}
                }
            }
            int tmp=min(c1,c2);
            if (tmp&1) puts("Ashish");else puts("Vivek");
        }
        return 0;
    }
    

    B

    注意到如果(0)(1)同时存在的话,我们可以借助一个不同类型的数来完成两个相同类型的数的交换,所以此时一定可以将序列排序。

    只存在一种类型的数时,无法进行任何操作,判断当前序列是否已排好序即可。

    int n,a[1010],b[1010],c[1010];
    
    int main()
    {
        int T=read();
        while (T--)
        {
            n=read();
            rep(i,1,n) a[i]=read();
            rep(i,1,n) b[i]=read();
            int c0,c1;c0=c1=0;
            rep(i,1,n)
                if (b[i]) c1=1;else c0=1;
            if ((c0) && (c1)) puts("Yes");
            else
            {
                rep(i,1,n) c[i]=a[i];
                sort(c+1,c+1+n);
                int ok=1;
                rep(i,1,n)
                    if (a[i]!=c[i]) ok=0;
                if (ok) puts("Yes");else puts("No");
            }
        }
        return 0;
    }
    

    C

    首先只用考虑向右位移,考虑若第(i)位上的两个数相同时需要的位移大小,这个大小可以被唯一确定,开个桶记一下即可。

    int n,a[200200],b[200200],c[200200],p[200200];
    
    int main()
    {
        n=read();
        rep(i,1,n) a[i]=read();
        rep(i,1,n) {b[i]=read();p[b[i]]=i;}
        rep(i,1,n)
        {
            int x=a[i],pos=p[x];
            int cnt=(i+n-pos);
            if (cnt>=n) cnt-=n;
            c[cnt]++;
        }
        int ans=0;
        rep(i,0,n-1) ans=max(ans,c[i]);
        printf("%d",ans);
        return 0;
    }
    

    D

    最直接的想法是不让B能四处移动,于是把每个B围一圈即可。

    注意特判掉G与B相连的情况。

    int n,m,sq[60][60],vis[60][60];
    char s[60][60];
    const int dx[]={1,0,-1,0},dy[]={0,1,0,-1};
    queue<pii> q;
    
    bool valid(int x,int y)
    {
        return ((x>=1) && (x<=n) && (y>=1) && (y<=m));
    }
    
    void bfs(int stx,int sty)
    {
        if (!sq[stx][sty]) return;
        q.push(mkp(stx,sty));vis[stx][sty]=1;
        while (!q.empty())
        {
            pii now=q.front();q.pop();
            int x=now.fir,y=now.sec;
            rep(i,0,3)
            {
                int nx=x+dx[i],ny=y+dy[i];
                if ((valid(nx,ny)) && (sq[nx][ny]) && (!vis[nx][ny]))
                {
                    vis[nx][ny]=1;
                    q.push(mkp(nx,ny));
                }
            }
        }
    }
    
    int main()
    {
        int T=read();
        while (T--)
        {
            n=read();m=read();
            rep(i,1,n) 
            {
                scanf("%s",s[i]+1);
                rep(j,1,m) sq[i][j]=(s[i][j]!='#');
            }
            int ok=1;
            rep(i,1,n) 
            {
                rep(j,1,m)
                {
                    if (s[i][j]=='B')
                    {
                        rep(k,0,3)
                        {
                            int nx=i+dx[k],ny=j+dy[k];
                            if (valid(nx,ny))
                            {
                                if (s[nx][ny]=='G') {ok=0;break;}
                                sq[nx][ny]=0;
                            }
                        }
                        if (!ok) break;
                    }
                }
                if (!ok) break;
            }
            if (!ok) {puts("No");continue;}
            bfs(n,m);
            rep(i,1,n) rep(j,1,m)
            {
                if ((s[i][j]=='G') && (!vis[i][j])) {ok=0;break;}
            }
            if (!ok) puts("No");else puts("Yes");
            rep(i,1,n) rep(j,1,m) vis[i][j]=0;
        }
        return 0;
    }
    

    E

    降智*1

    考虑最后集合可能的大小,注意到若当前集合为(3),新增加的元素不可能会在新的二进制位上产生贡献,因为此时已经有(3)个数不具有这个二进制位了,而这个不会贡献新的二进制位的元素显然是可以删掉的。

    所以我们只需要枚举不超过(3)的集合,取个or后再取个max即可。

    int n;
    ll a[510],ans=0;
    
    int main()
    {
        n=read();
        rep(i,1,n) a[i]=readll();
        ans=0;
        rep(i,1,n) rep(j,i,n) rep(k,j,n)
            ans=max(ans,a[i]|a[j]|a[k]);
        printf("%lld",ans);
        return 0;
    }
    

    F

    降智*2

    一个很重要的观察是:无论如何对数列(a)进行操作,数对((a_i,a_{n-i+1}))是不会被拆散的,于是我们得到了一个合法的必要条件。接下来考虑根据(b)序列从中间向两边构造,不难发现这样的构造方案是一定存在的。所以这个条件也是一个充分条件。开一个map维护所有的数对即可。

    int n,a[510],b[510];
    map<pii,int> mp;
    
    int main()
    {
        int T=read();
        while (T--)
        {
            n=read();mp.clear();
            rep(i,1,n) a[i]=read();
            rep(i,1,n) b[i]=read();
            rep(i,1,n/2) mp[mkp(a[i],a[n-i+1])]++;
            int ok=1;
            rep(i,1,n/2)
            {
                int x=b[i],y=b[n-i+1];
                if (mp[mkp(x,y)])
                {
                    mp[mkp(x,y)]--;
                }
                else if (mp[mkp(y,x)]) 
                {
                    mp[mkp(y,x)]--;
                }
                else {ok=0;break;}
            }
            if ((n&1) && (a[(n+1)/2]!=b[(n+1)/2])) ok=0;
            if (ok) puts("Yes");else puts("No");
        }
        return 0;
    }
    

    G

    一道有点意思(?)的交互.

    一个比较直接的想法是:将所有的下标的二进制表示写出来,记(x_i)为从低到高第(i)个二进制位为1的所有数的or值,那么在求(P_i)的时候只需要将i中为(0)的二进制位对应的(a)取出来取or。

    但是这样会有一个问题,如果一个数(j)(i)所有的二进制位,那么我们算出来的(P_i)是不会包含(a_j)的。最直接的处理方法就是再询问出(y_i)表示从低到高第(i)个二进制位为0的(a_i)的or值。但是这样的话询问次数就爆炸了。

    考虑如何避免上面出现的问题,我们需要给原来的下标赋上一个新的下标,使得不存在两个数(x,y)满足(x)不会拥有(y)所有的(1)二进制位。更形式化的,我们需要求出(n)个集合满足任意两个集合不存在包含关系。

    根据这个定理发现对于一个大小为(13)的集合,它的所有(6)元子集正好(>1000)且满足互不包含,这也是满足这个条件的一个下界。

    int n,sta[1010];
    ll ans[1010],cnt[10010],val[20];
    vi q[20];
    
    ll ask(vi id)
    {
        int len=id.size();
        if (!len) return 0;
        printf("? %d ",len);
        rep(i,0,len-1) printf("%d ",id[i]);
        puts("");fflush(stdout);
        ll val=readll();
        return val;
    }
    
    void answer()
    {
        printf("! ");
        rep(i,1,n) printf("%lld ",ans[i]);
        puts("");fflush(stdout);
    }
    
    int main()
    {
        n=read();int lim=(1<<13)-1;
        rep(i,1,lim) cnt[i]=cnt[i>>1]+(i&1);
        int now=0;
        rep(i,1,lim)
        {
            if (cnt[i]!=6) continue;
            sta[++now]=i;
            rep(j,0,12)
                if ((i>>j)&1) q[j].pb(now);
            if (now==n) break;
        }
        rep(i,0,12) val[i]=ask(q[i]);
        rep(i,1,n)
        {
            rep(j,0,12)
                if (((sta[i]>>j)&1)==0) 
                {
                    ans[i]|=val[j];
                }
        }
        answer();
        return 0;
    }
    
  • 相关阅读:
    工作记录(1)- js问题
    QComboBox样式
    VLC的一些接口
    Qt使用std::sort进行排序
    如何正确使用QThread
    QChartView绘制饼状图
    libcurl编译使用,实现ftp功能
    QSplineSeries QChartView绘制曲线
    QLineSeries QChartView 生成折线
    QChart绘制折线区域
  • 原文地址:https://www.cnblogs.com/encodetalker/p/13068750.html
Copyright © 2011-2022 走看看