zoukankan      html  css  js  c++  java
  • 2017NOIP游记

      记得去年这个时候,大概刚接触OI。没想到时间这么快,第一次2017NOIP之旅已经结束。初测成绩出来了,100+100+95+50=345,有浙江三十几名(@Cptraser 机房370大佬)。总体感觉还可以吧,也发挥的不错。但有些地方还是有点可惜。学校里的学长(@Cptraser)让我开个博客,我也想谨以此记录一下自己的点滴吧。

      贴的都是比赛时的原码

    T1 太搞笑的一题,虽然有很多人因为精度爆60(还好手动整数除)

    CODE

    #include<cstdio>
    using namespace std;
    int a,b,c;
    int main()
    {
        freopen("score.in","r",stdin); freopen("score.out","w",stdout);
        scanf("%d%d%d",&a,&b,&c);
        printf("%d",a/5+b*3/10+c/2);
        return 0;
    }

    T2 感觉今年PJ前两题今年来算是最水的吧,刚开始想打字符串的,后来仔细一想%%%一下就水了

    CODE

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    inline void read(int &x)
    {
        x=0; char ch=getchar();
        while (ch<'0'||ch>'9') ch=getchar();
        while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    }
    const int N=1005;
    int n,q,i,j,x,s[N],w;
    inline int Pow_10(int k)
    {
        int tot=1;
        for (int i=1;i<=k;++i)
        tot*=10;
        return tot;
    }
    int main()
    {
        freopen("librarian.in","r",stdin); freopen("librarian.out","w",stdout);
        read(n); read(q);
        for (i=1;i<=n;++i)
        read(s[i]);
        sort(s+1,s+n+1);
        for (i=1;i<=q;++i)
        {
            bool flag=0;
            read(w); read(x);
            for (j=1;j<=n;++j)
            if (s[j]%Pow_10(w)==x) { printf("%d
    ",s[j]); flag=1; break; }
            if (!flag) puts("-1");
        }
        return 0;
    }

    T3 从T3开始难度就有提升。BFS很简单;SPFA很简单; 然而我考试时都没想到,对着一个记搜调了2个半小时,导致我T4最后想到了单调队列优化然后没时间了

    先贴比赛CODE(158行)

    #include<cstdio>
    #include<cstring>
    using namespace std;
    inline void read(int &x)
    {
        x=0; char ch=getchar();
        while (ch<'0'||ch>'9') ch=getchar();
        while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    }
    const int M=105,fx[4]={0,1,0,-1},fy[4]={1,0,-1,0},INF=1e9;
    int map[M][M],n,m,i,j,x,y,z,ans=1e9,f[M][M][3],vis[M][M];
    inline int min(int a,int b) { return a<b?a:b; }
    void dfs(int x,int y)
    {
        bool flag=0;
        if (map[x][y]==0) flag=1;
        for (int i=0;i<4;++i)
        {
            int xx=fx[i]+x,yy=fy[i]+y;
            if (xx>0&&xx<=m&&yy>0&&yy<=m&&vis[xx][yy])
            {
                if (map[xx][yy])
                {
                    if (f[xx][yy][0]!=INF) 
                    {
                        if (flag) 
                        {
                            int add;
                            if (map[xx][yy]==1) add=0; else add=1;
                            f[x][y][1]=min(f[x][y][1],f[xx][yy][0]+add+2);
                            if (map[xx][yy]==2) add=0; else add=1;
                            f[x][y][2]=min(f[x][y][2],f[xx][yy][0]+add+2); 
                        } else
                        {
                            int add;
                            if (map[x][y]==map[xx][yy]) add=0; else add=1;
                            f[x][y][0]=min(f[x][y][0],f[xx][yy][0]+add);
                        }
                    } else
                    {
                        vis[xx][yy]=0;
                        dfs(xx,yy);
                        vis[xx][yy]=1;
                        if (flag) 
                        {
                            int add;
                            if (map[xx][yy]==1) add=0; else add=1;
                            f[x][y][1]=min(f[x][y][1],f[xx][yy][0]+add+2);
                            if (map[xx][yy]==2) add=0; else add=1;
                            f[x][y][2]=min(f[x][y][2],f[xx][yy][0]+add+2); 
                        } else
                        {
                            int add;
                            if (map[x][y]==map[xx][yy]) add=0; else add=1;
                            f[x][y][0]=min(f[x][y][0],f[xx][yy][0]+add);
                        }
                    }
                } else
                {
                    if (f[xx][yy][1]!=INF&&f[xx][yy][2]!=INF)
                    {
                        if (!flag) 
                        {
                            int add;
                            if (map[x][y]==1) add=0; else add=1;
                            f[x][y][0]=min(f[x][y][0],f[xx][yy][1]+add);
                            if (map[x][y]==2) add=0; else add=1;
                            f[x][y][0]=min(f[x][y][0],f[xx][yy][2]+add);
                        } 
                    } else 
                    { 
                        if (!flag)
                        {
                            vis[xx][yy]=0; 
                            dfs(xx,yy); 
                            vis[xx][yy]=1; 
                            int add;
                            if (map[x][y]==1) add=0; else add=1;
                            f[x][y][0]=min(f[x][y][0],f[xx][yy][1]+add);
                            if (map[x][y]==2) add=0; else add=1;
                            f[x][y][0]=min(f[x][y][0],f[xx][yy][2]+add);
                        }
                    }
                }
            }
        }
    }
    void xz()
    {
        for (int i=1;i<=m;++i)
        for (int j=1;j<=m;++j)
        {
            if (map[i][j]) 
            {
                for (int k=0;k<4;++k)
                {
                    int x=fx[k]+i,y=fy[k]+j;
                    if (x>0&&x<=m&&y>0&&y<=m) 
                    {
                        if (map[x][y]) 
                        {
                            int add;
                            if (map[x][y]==map[i][j]) add=0; else add=1;
                            f[i][j][0]=min(f[i][j][0],f[x][y][0]+add);
                        } else
                        {
                            int add;
                            if (map[i][j]==1) add=0; else add=1;
                            f[i][j][0]=min(f[i][j][0],f[x][y][1]+add);
                            if (map[i][j]==2) add=0; else add=1;
                            f[i][j][0]=min(f[i][j][0],f[x][y][2]+add);
                        }
                    }
                }
            } else
            {
                for (int k=0;k<4;++k)
                {
                    int x=fx[k]+i,y=fy[k]+j;
                    if (x>0&&x<=m&&y>0&&y<=m)
                    {
                        if (map[x][y])
                        {
                            int add;
                            if (map[x][y]==1) add=0; else add=1;
                            f[i][j][1]=min(f[i][j][1],f[x][y][0]+add+2);
                            if (map[x][y]==2) add=0; else add=1;
                            f[i][j][2]=min(f[i][j][2],f[x][y][0]+add+2);
                        }
                    }
                }
            }
        }
    }
    int main()
    {
        freopen("chess.in","r",stdin); freopen("chess.out","w",stdout);
        memset(map,0,sizeof(map));
        memset(vis,true,sizeof(vis));
        read(m); read(n);
        for (i=1;i<=m;++i)
        for (j=1;j<=m;++j)
        f[i][j][0]=f[i][j][1]=f[i][j][2]=INF;
        f[1][1][0]=0;
        for (i=1;i<=n;++i)
        {
            read(x); read(y); read(z);
            map[x][y]=z+1;
        }
        vis[m][m]=0;
        dfs(m,m);
        xz();
        bool flag=0;
        if (map[m][m]==0) flag=1;
        if (flag) { if (min(f[m][m][1],f[m][m][2])==INF) puts("-1"); else printf("%d",min(f[m][m][1],f[m][m][2])); }
        else { if (f[m][m][0]==INF) puts("-1"); else printf("%d",f[m][m][0]); }
        return 0;
    }

    上面的dfs其实在搞笑,真正得(骗)了95分的是那个最后10分钟加上去的xz(),%%%%%%

    回来后仔细想了想,打了个SPFA,就是建边的过程有点烦

    对于每个有颜色的点

    距离为1的有颜色的点颜色相同连1条0的边;颜色不同连一条1的边;

    距离为2的有颜色的点颜色相同连1条2的边;颜色不同连一条3的边;

    最后对于(m,m)有无颜色的问题特判一下就过了,代码量明显减少

    CODE

    #include<cstdio>
    #include<vector>
    #include<cstring>
    using namespace std;
    const int fx1[4]={0,1,0,-1},fy1[4]={1,0,-1,0},fx2[8]={0,0,-2,2,-1,-1,1,1},fy2[8]={-2,2,0,0,-1,1,-1,1};
    const int M=105;
    int map[M][M],INF,father[M*M+10],i,x,y,z,n,m,j,dis[M*M+10],q[M*M*2+10],f[M*M+10],head,tail;
    vector <int> a[M*M+10],l[M*M+10];
    inline void read(int &x)
    {
        x=0; char ch=getchar();
        while (ch<'0'||ch>'9') ch=getchar();
        while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    }
    void build(int x,int y)
    {
        for (int i=0;i<4;++i)
        {
            int xx=x+fx1[i],yy=y+fy1[i];
            if (map[xx][yy]!=INF&&xx>0&&yy>0&&xx<=m&&yy<=m) 
            a[(x-1)*m+y].push_back((xx-1)*m+yy),l[(x-1)*m+y].push_back(map[x][y]!=map[xx][yy]);
        }
        for (int i=0;i<8;++i)
        {
            int xx=x+fx2[i],yy=y+fy2[i];
            if (map[xx][yy]!=INF&&xx>0&&yy>0&&xx<=m&&yy<=m) 
            a[(x-1)*m+y].push_back((xx-1)*m+yy),l[(x-1)*m+y].push_back(map[x][y]==map[xx][yy]?2:3);
        }
    }
    int main()
    {
        freopen("chess.in","r",stdin); freopen("chess.out","w",stdout);
        read(m); read(n);
        memset(map,63,sizeof(map));
        memset(dis,63,sizeof(dis));
        for (i=1;i<=n;++i)
        {
            read(x); read(y); read(z); 
            map[x][y]=z;
        }
        INF=map[0][0];
        for (i=1;i<=m;++i)
        for (j=1;j<=m;++j)
        if (map[i][j]!=INF) build(i,j);
        dis[1]=0; q[1]=1; f[1]=1;
        head=0; tail=1;
        while (head<tail)
        {
            int now=q[++head];
            f[now]=0;
            for (i=0;i<a[now].size();++i)
            {
                int k=a[now][i];
                if (dis[k]>dis[now]+l[now][i])
                {
                    dis[k]=dis[now]+l[now][i];
                    if (!f[k])
                    {
                        q[++tail]=k;
                        f[k]=1;
                    }
                }
            }
        }
        if (map[m][m]==INF) 
        {
            if (map[m][m-1]!=INF) dis[m*m]=min(dis[m*m],dis[m*m-1]+2);
            if (map[m-1][m]!=INF) dis[m*m]=min(dis[m*m],dis[m*m-m]+2);
        }
        if (dis[m*m]==INF) puts("-1"); else printf("%d",dis[m*m]);
        return 0;
    }

    T4 谨记机房大佬(@Cptraser)的教诲,NOIP已经很久很久没有考MST了。然而今年,一如既往的没考。

    最后一题 看一眼 二分答案,check()

              再一看 二维DP也许能行 20分钟打好

                   然后优化第三题去了 然后再也没有回来

    比赛CODE

    #include<cstdio>
    #include<cstring>
    typedef long long LL;
    using namespace std;
    inline void read(LL &x)
    {
        x=0; char ch=getchar(); LL flag=1;
        while (ch<'0'||ch>'9') { if (ch=='-') flag=-1; ch=getchar(); }
        while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
        x*=flag;
    }
    const LL N=500005;
    struct data
    {
        LL x,w;
    }a[N];
    LL n,d,k,i,j,ans=-1,sum=0,f[N];
    inline LL max(LL a,LL b) { return a>b?a:b; }
    bool check(LL x)
    {
        LL left=x<d?d-x:1,right=d+x;
        for (i=1;i<=n;++i)
        f[i]=-1e9;
        for (i=1;i<=n;++i)
        for (j=0;j<i;++j)
        if (a[i].x-a[j].x>=left&&a[i].x-a[j].x<=right) 
        {
            f[i]=max(f[i],f[j]+a[i].w);
            if (f[i]>=k) return 1;
        }
        return 0;
    }
    int main()
    {
        freopen("jump.in","r",stdin); freopen("jump.out","w",stdout);
        read(n); read(d); read(k);    
        for (i=1;i<=n;++i)
        read(a[i].x),read(a[i].w),sum+=a[i].w>0?a[i].w:0;
        if (sum<k) { puts("-1"); return 0; }
        if (d==1)
        {
            sum=0;
            for (i=1;i<=n;++i)
            {
                sum+=a[i].w;
                if (sum>=k) { puts("0"); return 0; }
            }
        }
        a[0].x=a[0].w=0;
        LL l=0,r=a[n].x;
        while (l<=r)
        {
            LL mid=(l+r)>>1;
            if (check(mid)) ans=mid,r=mid-1; else l=mid+1;
        }
        printf("%lld",ans);
        return 0;
    }

                   那个 d==1 的特判其实是在搞笑

         单调队列的优化还是很好想的

                   在距离内的加入,距离外的弹出,为了取最大最优值只需要保持队列单调递减即可。

         借鉴了洛谷一名大佬的思路

    CODE

    #include<cstdio>
    #include<cstring>
    typedef long long LL;
    using namespace std;
    inline void read(LL &x)
    {
        x=0; char ch=getchar(); LL flag=1;
        while (ch<'0'||ch>'9') { if (ch=='-') flag=-1; ch=getchar(); }
        while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
        x*=flag;
    }
    const LL N=500005;
    struct data
    {
        LL x,w;
    }a[N];
    struct dl
    {
        LL x,s;
    }q[N*2+10];
    LL n,d,k,i,j,ans=-1,sum=0,f[N],head,tail,now;
    inline LL max(LL a,LL b) { return a>b?a:b; }
    bool check(LL x)
    {
        LL left=x<d?d-x:1,right=d+x;
        for (i=1;i<=n;++i)
        f[i]=-1e9;
        q[0].x=q[0].s=0; head=0; tail=-1; now=0;
        for (i=1;i<=n;++i)
        {
            for (now;(a[now].x<=a[i].x-left)&&(now<i);++now)
            {
                while (head<=tail&&q[tail].s<f[now]) --tail;
                if (f[now]==-1e9) continue;
                q[++tail].x=a[now].x; q[tail].s=f[now];
            }
            while (head<=tail&&a[i].x-q[head].x>right) head++;
            if (head<=tail) f[i]=q[head].s+a[i].w;
            if (f[i]>=k) return 1;
        }
        return 0;
    }
    int main()
    {
        freopen("jump.in","r",stdin); freopen("jump.out","w",stdout);
        read(n); read(d); read(k);    
        for (i=1;i<=n;++i)
        read(a[i].x),read(a[i].w),sum+=a[i].w>0?a[i].w:0;
        if (sum<k) { puts("-1"); return 0; }
        /*if (d==1)
        {
            sum=0;
            for (i=1;i<=n;++i)
            {
                sum+=a[i].w;
                if (sum>=k) { puts("0"); return 0; }
            }
        }*/
        a[0].x=a[0].w=0;
        LL l=0,r=a[n].x;
        while (l<=r)
        {
            LL mid=(l+r)>>1;
            if (check(mid)) ans=mid,r=mid-1; else l=mid+1;
        }
        printf("%lld",ans);
        return 0;
    }

      暑假才P->C,代码有点chou

      其实今年的O气真的很足,第三题水了95

      感觉今年总体难度比去年低吧,但浙江的分数线才280(据说)……

      有点小兴奋吧,毕竟一年的付出没有白费

      明年再接再厉,准备下提高吧

      顺便宣传下大佬的博客(@Cptraser)http://www.cnblogs.com/Cptraser/

    辣鸡老年选手AFO在即
  • 相关阅读:
    【五月每日总结】
    【Codeforces Round #405 ( Div 2)】题解
    【Codeforces Round #406 (Div. 2)】题解
    【HUD-5790】Prefix (主席树+tire)
    【倍增】LCM QUERY
    【hackerrank】Week of Code 30
    【Codeforces Round #404 (Div. 2)】题解
    【数论】逆元
    mongodb复制集部署文档
    合并SQL 调优
  • 原文地址:https://www.cnblogs.com/cjjsb/p/7880444.html
Copyright © 2011-2022 走看看