zoukankan      html  css  js  c++  java
  • Codeforces Round #403 (Div. 1, based on Technocup 2017 Finals)

    Div1单场我从来就没上过分,这场又剧毒,半天才打出B,C挂了好几次最后还FST了,回紫了。

    AC:AB Rank:340 Rating:2204-71->2133

    Div2.B.The Meeting Place Cannot Be Changed

    题目大意:n个人,第i个人位于xi,速度为vi,找到一个点使得所有人到这个点的耗时最小,输出耗时。(n<=60000)

    思路:二分答案,知道耗时后可以求出每个人能到达的区间,如果所有区间有交则合法,复杂度O(nlog)。

    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    char B[1<<26],*S=B,C;int X;
    inline int read()
    {
        while((C=*S++)<'0'||C>'9');
        for(X=C-'0';(C=*S++)>='0'&&C<='9';)X=(X<<3)+(X<<1)+C-'0';
        return X;
    }
    #define MN 60000
    int x[MN+5],v[MN+5];
    int main()
    {
        fread(B,1,1<<26,stdin);
        int n=read(),i,p;double l=0,r=0x3FFFFFFF,mid,mn,mx,ans;
        for(i=1;i<=n;++i)x[i]=read();
        for(i=1;i<=n;++i)v[i]=read();
        for(p=1;p<=100;++p)
        {
            mid=(l+r)/2;
            for(mn=1e18,mx=-1e18,i=1;i<=n;++i)
                mn=min(mn,x[i]+mid*v[i]),mx=max(mx,x[i]-mid*v[i]);
            if(mx-mn<1e-12)ans=r=mid;
            else l=mid;
        }
        printf("%.12lf",ans);
    }

    A.Andryusha and Colored Balloons

    题目大意:给出一棵n个点的树,距离为2以内的点颜色不能相同,求最小染色方案。(n<=200,000)

    思路:每个点对他的儿子染色,每个儿子颜色不与他和他父亲还有染过的儿子颜色相同即可,复杂度O(n)。

    #include<cstdio>
    char B[1<<26],*S=B,C;int X;
    inline int read()
    {
        while((C=*S++)<'0'||C>'9');
        for(X=C-'0';(C=*S++)>='0'&&C<='9';)X=(X<<3)+(X<<1)+C-'0';
        return X;
    }
    #define MN 200000
    struct edge{int nx,t;}e[MN*2+5];
    int h[MN+5],en,r[MN+5],fa[MN+5],c[MN+5];
    inline void ins(int x,int y){e[++en]=(edge){h[x],y};h[x]=en;}
    void dfs(int x)
    {
        int i,j=0;
        for(i=h[x];i;i=e[i].nx)if(e[i].t!=fa[x])
        {
            while(c[x]==++j||c[fa[x]]==j);
            c[e[i].t]=j;fa[e[i].t]=x;dfs(e[i].t);
        }
    }
    int main()
    {
        fread(B,1,1<<26,stdin);
        int n=read(),i,x,y,rt=0;
        for(i=1;i<n;++i)
        {
            if(++r[x=read()]>r[rt])rt=x;
            if(++r[y=read()]>r[rt])rt=y;
            ins(x,y);ins(y,x);
        }
        printf("%d
    ",r[rt]+1);
        dfs(c[1]=1);
        for(i=1;i<=n;++i)printf("%d ",c[i]);
    }

    B.Innokenty and a Football League

    题目大意:n支球队要取名,每支球队有两种选择,要求:1.所有球队名字不能相同;2.如果两支球队第一种选择相同,他们都只能选第二种。(n<=1000)

    思路:转化成2-sat模板题就可以了。2-sat构造解我不是很熟练,打了很久。

    #include<iostream>
    using namespace std;
    #define MN 1000
    #define MV 2000
    #define ME 5000000
    string s[MN+5][2],sa,sb;
    struct edge{int nx,t;}e[ME*2+5];
    int h[MV+5],en,d[MV+5],l[MV+5],cnt,z[MV+5],zn,inz[MV+5],b[MV+5],bn;
    int rh[MV+5],r[MV+5],c[MV+5],q[MV+5],qn;
    inline void ins(int*h,int x,int y){e[++en]=(edge){h[x],y};h[x]=en;}
    void tj(int x)
    {
        d[x]=l[x]=++cnt;inz[z[zn++]=x]=1;
        for(int i=h[x];i;i=e[i].nx)
        {
            if(!d[e[i].t])tj(e[i].t);
            if(inz[e[i].t]&&l[e[i].t]<l[x])l[x]=l[e[i].t];
        }
        if(d[x]==l[x])for(++bn;z[zn]!=x;inz[z[zn]]=0)b[z[--zn]]=bn;
    }
    int main()
    {
        int n,i,j,k;
        cin>>n;
        for(i=1;i<=n;++i)
        {
            cin>>sa>>sb;
            s[i][0]=s[i][1]=s[i][0]+sa[0]+sa[1];
            s[i][0]+=sa[2];s[i][1]+=sb[0];
        }
        for(i=1;i<=n;++i)for(j=1;j<=n;++j)if(i!=j)
        {
            if(s[i][0]==s[j][0])ins(h,i,j+n),ins(h,i+n,j+n);
            if(s[i][0]==s[j][1])ins(h,i,j);
            if(s[i][1]==s[j][0])ins(h,i+n,j+n);
            if(s[i][1]==s[j][1])ins(h,i+n,j);
        }
        for(i=1;i<=n<<1;++i)if(!d[i])tj(i);
        for(i=1;i<=n;++i)if(b[i]==b[i+n])return puts("NO"),0;
        puts("YES");
        for(i=1;i<=n<<1;++i)for(j=h[i];j;j=e[j].nx)
            if(b[i]!=b[e[j].t])ins(rh,b[e[j].t],b[i]),++r[b[i]];
        for(i=1;i<=bn;++i)if(!r[i])q[++qn]=i;
        for(i=1;i<=qn;++i)
        {
            if(!c[q[i]])
            {
                for(j=1;j<=n;++j)if(b[j]==q[i])c[b[j+n]]=1;
                for(;j<=n<<1;++j)if(b[j]==q[i])c[b[j-n]]=1;
            }
            for(j=rh[q[i]];j;j=e[j].nx)if(!--r[e[j].t])q[++qn]=e[j].t;
        }
        for(i=1;i<=n;++i)cout<<(c[b[i]]?s[i][1]:s[i][0])<<endl;
    }

    C.Underground Lab

    题目大意:给出n个点m条边的无向联通图,构造k条长度不超过2n/k(向上取整)的路径覆盖所有点。(n,m<=200,000,k<=n)

    思路:考虑该图的一颗生成树,dfs一遍,进入节点和从子节点回来时都把当前点加入路径里,就得到一个长度为2n-1的路径覆盖,分成k段输出即可,复杂度O(n)。我输出写的巨丑挂了,非常难受。

    AC代码

    #include<cstdio>
    char B[1<<26],*S=B,C;int X;
    inline int read()
    {
        while((C=*S++)<'0'||C>'9');
        for(X=C-'0';(C=*S++)>='0'&&C<='9';)X=(X<<3)+(X<<1)+C-'0';
        return X;
    }
    #define MN 200000
    struct edge{int nx,t;}e[MN*2+5];
    int f[MN+5],h[MN+5],en,ans[MN*2+5],cnt;
    int gf(int k){return f[k]?f[k]=gf(f[k]):k;}
    inline void ins(int x,int y){e[++en]=(edge){h[x],y};h[x]=en;}
    void dfs(int x,int fa)
    {
        ans[++cnt]=x;
        for(int i=h[x];i;i=e[i].nx)if(e[i].t!=fa)
        {
            dfs(e[i].t,x);
            ans[++cnt]=x;
        }
    }
    int main()
    {
        fread(B,1,1<<26,stdin);
        int n,m,k,x,y,i,j;
        n=read();m=read();k=read();
        while(m--)
        {
            x=read();y=read();
            if(gf(x)!=gf(y))f[gf(x)]=gf(y),ins(x,y),ins(y,x);
        }
        dfs(1,0);--cnt;
        for(x=1;x*k<cnt;++x);
        for(i=1;i<=k;++i)
        {
            printf("%d ",x);
            for(j=1;j<=x;++j)printf("%d ",cnt?ans[((i-1)*x+j-1)%cnt+1]:1);
            puts("");
        }
    }

    D.Axel and Marston in Bitland

    题目大意:给出一张n个点m条边的图,边权为0或1,按以下方式构造一个01序列:一开始为0,每次将当前串取反加到原串后面(0,01,0110,01101001……),问从点1出发,按这个01序列走对应边权的边,最多能走多少步,如果超过10^18输出-1。(n<=500,m<=2*n^2)

    思路:令s[i][0/1]表示长度为2^i的原串/取反串,则有s[i+1][0]=s[i][0]+s[i][1],s[i+1][1]=s[i][1]+s[i][0],我们把原图按这个方式bitset加速倍增一下,然后DP就可以了,复杂度O(n^3/32*log10^18),时限5s而且cf机子快,非常科学。

    #include<cstdio>
    #include<cstring>
    #include<bitset>
    #include<algorithm>
    #include<iostream>
    using namespace std;
    inline int read()
    {
        int x;char c;
        while((c=getchar())<'0'||c>'9');
        for(x=c-'0';(c=getchar())>='0'&&c<='9';)x=(x<<3)+(x<<1)+c-'0';
        return x;
    }
    #define MN 500
    #define MK 60
    #define INF 1000000000000000000LL
    bitset<MN+5> g[MK+5][2][MN+5];
    long long f[MK+5][MN+5][2],ans;
    int main()
    {
        int n,m,i,j,k,x,y;
        n=read();m=read();
        while(m--)
        {
            x=read();y=read();
            g[0][read()][x][y]=1;
        }
        for(k=0;k<MK;++k)for(i=1;i<=n;++i)for(j=1;j<=n;++j)
        {
            if(g[k][0][i][j])g[k+1][0][i]|=g[k][1][j];
            if(g[k][1][i][j])g[k+1][1][i]|=g[k][0][j];
        }
        memset(f,128,sizeof(f));f[k+1][1][0]=0;
        for(k=MK;k>=0;--k)
        {
            for(i=1;i<=n;++i)f[k][i][0]=f[k+1][i][0],f[k][i][1]=f[k+1][i][1];
            for(i=1;i<=n;++i)for(j=1;j<=n;++j)
            {
                if(g[k][0][i][j])f[k][j][1]=max(f[k][j][1],f[k+1][i][0]+(1LL<<k));
                if(g[k][1][i][j])f[k][j][0]=max(f[k][j][0],f[k+1][i][1]+(1LL<<k));
            }
        }
        for(i=1;i<=n;++i)ans=max(ans,max(f[0][i][0],f[0][i][1]));
        cout<<(ans>INF?-1:ans);
    }
  • 相关阅读:
    Day3-spark基本认识
    团队冲刺第九天
    团队冲刺第八天
    团队冲刺第七天
    团队冲刺第六天
    团队冲刺第五天
    团队冲刺第四天
    团队冲刺第三天
    团队冲刺第二天
    团队冲刺第一天
  • 原文地址:https://www.cnblogs.com/ditoly/p/CF403.html
Copyright © 2011-2022 走看看