zoukankan      html  css  js  c++  java
  • Codeforces Round #408(div.2)

    来自FallDream的博客,未经允许,请勿转载,谢谢。


    凌晨打比赛真的难受,十一点趴下去,一觉起来感觉精神非常迷糊  脑子不好使了

    ------------------------------------------------------------------------------

    A. Buying A House

    给定n个点,每个点有一个价格。你有一些钱,你要求钱够买的情况下,离一个特殊点的最近距离。

    小模拟

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<map>
    #include<queue>
    #include<algorithm>
    #include<set>
    #include<cmath>
    #define MN 10005
    #define INF 200000000
    using namespace std;
    int read()
    {
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();}
        return x*f;
    }
    
    
    int n,s[MN+5],m,ans=INF,k;
    
    int abs(int x){return  x<0?-x:x;}
    
    int main()
    {
        n=read();k=read();m=read();
        for(int i=1;i<=n;i++)s[i]=read();
        for(int i=1;i<=n;i++)if(s[i]&&s[i]<=m)
            ans=min(ans,abs(k-i));
        printf("%d
    ",ans*10);
        return 0;
    }

    B. Find The Bone
    有n个位置,一个球放在位置1,有m个位置有洞。k个操作,每次交换两个位置的东西,如果球到了洞上面,他就会掉下去,求球的最后位置。

    大模拟

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<map>
    #include<queue>
    #include<algorithm>
    #include<set>
    #include<cmath>
    #define MN 1000005
    #define INF 200000000
    using namespace std;
    int read()
    {
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();}
        return x*f;
    }
    
    int n,m,k,pos=1;
    bool b[MN+5];
    
    int main()
    {
        n=read();m=read();k=read();
        for(int i=1;i<=m;i++)b[read()]=1;
        if(b[1])return 0*puts("1");
        for(int i=1;i<=k;i++)
        {
            int u=read(),v=read();
            if(u==pos)
            {
                pos=v;if(b[v])return 0*printf("%d
    ",v);
            }
            else if(v==pos)
            {
                pos=u;if(b[u])return 0*printf("%d
    ",u);
            }
        }
        printf("%d
    ",pos);
        return 0;
    }

    C. Bank Hacking

    有一棵n个节点的树,每个节点有一个权值,你要先选择一个节点,然后破坏它,与这个点连通且距离小等于2的点权值+1,然后你不断选择一个已经破坏的点的相邻节点破坏,求破坏的最大权值的最小值  n<=300000

    很容易发现是选择一个点不变,与他相邻的+1,其它+2,取一个最大值。所以可以直接暴力枚举,算一下有多少个最大值和 与每个点相邻的最大值有几个  就可以轻松算出答案。

    我菜,写了线段树。

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<map>
    #include<queue>
    #include<algorithm>
    #include<set>
    #include<cmath>
    #define ll long long
    #define N 524288
    #define MN 300005
    #define INF 2000000000
    using namespace std;
    int read()
    {
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();}
        return x*f;
    }
    
    struct edge{int to,next;}e[MN*5];
    int cnt=0,n,a[MN+5],head[MN+5],ans=INF;
    int T[MN*10];
    
    void renew (int x,int ad)
    {
        T[x+=N]=ad;
        for(x>>=1;x;x>>=1)
            T[x]=max(T[x<<1],T[x<<1|1]);
    }
    
    int query(int l,int r)
    {
        int sum=-INF;
        for(l+=N-1,r+=N+1;l^r^1;l>>=1,r>>=1)
        {
            if(~l&1) sum=max(sum,T[l+1]);
            if( r&1) sum=max(sum,T[r-1]);
        }
        return sum;
    }
    
    void ins(int f,int t)
    {
        e[++cnt]=(edge){t,head[f]};head[f]=cnt;
        e[++cnt]=(edge){f,head[t]};head[t]=cnt;
    }
    
    int main()
    {
        n=read();
        memset(T,128,sizeof(T));
        for(int i=1;i<=n;i++)
            a[i]=read(),renew(i,a[i]+2);
        for(int i=1;i<n;i++)
        {
            int x=read(),y=read();
            ins(x,y);
        }
        for(int x=1;x<=n;x++)
        {
            renew(x,a[x]);
            for(int i=head[x];i;i=e[i].next)
                renew(e[i].to,a[e[i].to]+1);
            ans=min(ans,query(1,n));
            renew(x,a[x]+2);
            for(int i=head[x];i;i=e[i].next)
                renew(e[i].to,a[e[i].to]+2);
        }
        printf("%d
    ",ans);
        return 0;
    }

    D.给定一棵树,一些节点是特殊节点,满足所有点到最近的特殊节点的距离不超过d,你要删去尽可能多的边,并且保证这个条件依旧满足,输出删去的数量和方案。

    考虑从每个特殊节点开始bfs,如果一条边到的节点已经被bfs到了,删掉它。注意去重。

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<map>
    #include<queue>
    #include<algorithm>
    #include<set>
    #include<cmath>
    #define ll long long
    #define MN 300005
    #define INF 200000000
    using namespace std;
    inline int read()
    {
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();}
        return x*f;
    }
    
    struct edge{int to,next;}e[MN*5];
    int cnt=1,n,k,mx,head[MN+5],d[MN+5],num,q[MN+5],sum=0,fa[MN+5],ans[MN+5];
    
    void ins(int f,int t)
    {
        e[++cnt]=(edge){t,head[f]};head[f]=cnt;
        e[++cnt]=(edge){f,head[t]};head[t]=cnt;
    }
    
    int main()
    {
        n=read();k=read();mx=read();
        memset(d,42,sizeof(d));
        for(int i=1;i<=k;i++)
        {
            int x=read();if(d[x]<INF)continue;
            q[++num]=x;d[x]=0;
        }
        for(int i=1;i<n;i++) ins(read(),read());
        for(int i=1;i<=num;i++)
            for(int j=head[q[i]];j;j=e[j].next)
            if(e[j].to!=fa[q[i]])
            {
                if(d[e[j].to]<INF) sum+=ans[j>>1]^1,ans[j>>1]=1;
                else d[q[++num]=e[j].to]=d[q[i]]+1,fa[e[j].to]=q[i];
            }
        printf("%d
    ",sum);
        for(int i=1;i<n;i++)
            if(ans[i]) printf("%d ",i);
        return 0;
    }

    E 有n道题,你可以偷看p次答案,每次只能看连续的k道题。但是你只能看相邻的两个人,并且这些人不一定都是对的。
    给出n,p,k和两个人分别有哪些题使得对的,求最多能看对(#滑稽)几道题  n,p<=1000 k<=50

    考虑dp,用f[i][j][x][y]表示前i道题,看了j次,第一个人还能看x道题,第二个人还能看y道题。每次转移i后移一格之后,x,y都会-1(如果它不是0),也就是说看了这一题。当然,你也可以选择让j+1使得x和y变成k-1,也就是从这里开始看,后面的k-1道题当然都能看到啦。(感觉讲的不清不楚)

    这样复杂度就是$O(npk^{2})$,不能通过此题,但是我们发现$pgeqslant 2lceilfrac{n}{k} ceil$的时候,我一定能看到所有题,只要这两个人有人做对了它。

    这样p最大变成2n/k,复杂度降低为$O(n^{2}k)$,足够通过。空间的话,我们把第一维滚动一下呗。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define INF 30000
    using namespace std;
    inline int read()
    {
        int x = 0 , f = 1; char ch = getchar();
        while(ch < '0' || ch > '9'){ if(ch == '-') f = -1;  ch = getchar();}
        while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();}
        return x * f;
    }
    
    int n,p,k,m;
    short f[2][1003][53][53];
    bool s[2][1003];
    
    inline void R(short&x,short y){if(y>x)x=y;}
    
    int main()
    {
        memset(f,128,sizeof(f));
        n=read();p=read();k=read();
        m=read();for(int i=1;i<=m;i++) s[0][read()]=1;
        m=read();for(int i=1;i<=m;i++) s[1][read()]=1;
        if(p>=(n+k-1)/k*2) 
        {
            int ans=0;
            for(int i=1;i<=n;i++) ans+=s[0][i]|s[1][i];
            return 0*printf("%d
    ",ans);
        } 
        f[0][0][0][0]=0;
        for(int i=0,now=1,pre=0;i<n;i++,now^=1,pre^=1)
        {
            for(int j=0;j<=p;j++)    
            {             
                for(int x=0;x<=k;x++)
                    for(int y=0;y<=k;y++)
                    {
                        if(!x&&!y) 
                        {
                            R(f[now][j][0][0],f[pre][j][0][0]);
                            R(f[now][j+1][0][k-1],f[pre][j][0][0]+s[1][i+1]);
                            R(f[now][j+1][k-1][0],f[pre][j][0][0]+s[0][i+1]);
                            R(f[now][j+2][k-1][k-1],f[pre][j][0][0]+(s[0][i+1]|s[1][i+1])); 
                        } 
                        else if(!x)
                        {
                            R(f[now][j][0][y-1],f[pre][j][0][y]+s[1][i+1]);
                            R(f[now][j+1][k-1][y-1],f[pre][j][0][y]+(s[0][i+1]|s[1][i+1]));
                            R(f[now][j+2][k-1][k-1],f[pre][j][0][y]+(s[0][i+1]|s[1][i+1]));
                        }
                        else if(!y)
                        {
                              R(f[now][j][x-1][0],f[pre][j][x][0]+s[0][i+1]);
                              R(f[now][j+1][x-1][k-1],f[pre][j][x][0]+(s[0][i+1]|s[1][i+1]));
                              R(f[now][j+2][k-1][k-1],f[pre][j][x][0]+(s[0][i+1]|s[1][i+1]));
                        }    
                        else 
                            R(f[now][j][x-1][y-1],f[pre][j][x][y]+(s[1][i+1]|s[0][i+1]));
                        f[pre][j][x][y]=-INF;
                    }
            }    
        }    
        short ans=0;
        for(int x=0;x<k;x++)
            for(int y=0;y<k;y++)
                R(ans,f[n&1][p][x][y]);
        printf("%d
    ",(int)ans);
        return 0;
    }
  • 相关阅读:
    LeetCode 538----Convert BST to Greater Tree
    LeetCode 543---- Diameter of Binary Tree
    springboot请求体中的流只能读取一次的问题
    bind9+dlz+mysql连接断开问题
    关于Java的Object.clone()方法与对象的深浅拷贝
    HashSet怎样保证元素不重复
    percona-toolkit主从同步整理(MySQL)
    MySQL主从配置
    关于自动化部署平台的尝试
    struts2使用注解的时候遇到的问题
  • 原文地址:https://www.cnblogs.com/FallDream/p/codeforces408.html
Copyright © 2011-2022 走看看