zoukankan      html  css  js  c++  java
  • FR #11题解

    A.

      瞎jb折半dp一下,然后合并一下就好了。

          O2加成十分显著。。。6s变成0.9s。。。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<bitset>
    #define maxv 100
    #define maxe 20000
    using namespace std;
    int n,m,d,x,y,z,g[maxv],nume=1,s1,s2,ans=0;
    struct edge
    {
        int v,f,nxt;
    }e[maxe];
    bitset <maxv> dp1[maxv][(1<<10)+1][2],dp2[maxv][(1<<10)+1][2];
    bitset <1030> vvv[maxv],kr;
    bool vis[(1<<20)+1],arr[maxv][15];
    void addedge(int u,int v,int f)
    {
        e[++nume].v=v;e[nume].f=f;
        e[nume].nxt=g[u];g[u]=nume;
    }
    void dp1s()
    {
        for (register int i=1;i<=s1;i++)
        {
            for (register int j=1;j<=n;j++)
                for (register int k=0;k<(1<<s1);k++)
                    dp1[j][k][i&1].reset();
            for (register int j=1;j<=n;j++)
                for (register int k=g[j];k;k=e[k].nxt)
                {
                    int v=e[k].v,f=e[k].f,rr=i&1;
                    for (register int s=0;s<(1<<(i-1));s++)
                        dp1[j][(s<<1)|f][rr]|=dp1[v][s][rr^1];
                    arr[j][i]|=arr[v][i-1];
                }
        }
    }
    void dp2s()
    {
        for (register int i=1;i<=s2;i++)
        {
            for (register int j=1;j<=n;j++)
                for (register int k=0;k<(1<<s2);k++)
                    dp2[j][k][i&1].reset();
            for (register int j=1;j<=n;j++)
                for (register int k=g[j];k;k=e[k].nxt)
                {
                    int v=e[k].v,f=e[k].f,rr=i&1;
                    for (register int s=0;s<(1<<(i-1));s++)
                        dp2[j][(s<<1)|f][rr]|=dp2[v][s][rr^1];
                }
        }
    }
    void comb()
    {
        for (register int i=1;i<=n;i++)
            for (register int j=0;j<(1<<s1);j++)
                if (dp1[i][j][s1&1].count())
                    vvv[i][j]=1;
        for (register int i=1;i<=n;i++)
            for (register int j=0;j<(1<<s2);j++)
            {
                if (dp2[i][j][s2&1].count())
                {
                    kr.reset();
                    for (register int k=1;k<=n;k++) 
                        if (dp2[i][j][s2&1][k])
                            kr|=vvv[k];
                    for (register int k=0;k<(1<<s1);k++)
                    {
                        if (kr[k])
                            vis[k<<s2|j]=true;
                    }
                }
            }                                                                                                                                                                                                                                                                                                                          
    }
    int main()
    { 
        scanf("%d%d%d",&n,&m,&d);
        for (register int i=1;i<=m;i++)
        {
            scanf("%d%d%d",&x,&y,&z);
            addedge(x,y,z);addedge(y,x,z);    
        }    
        s1=d/2;s2=d-s1;arr[1][0]=true;dp1[1][0][0][1]=1;
        dp1s();
        for (register int i=1;i<=n;i++)
            if (arr[i][s1]) dp2[i][0][0][i]=1;
        dp2s();
        comb();
        for (register int i=0;i<(1<<d);i++) ans+=vis[i];
        printf("%d
    ",ans);
        return 0;
    }

    B.

       考虑倒着做。这个答案只会单增,于是枚举答案然后check。

         怎么check呢?考虑枚举所有这么长的包含这辆车的这一行中的区间,每个位置记下它上面和下面的第一个点(车)的位置,然后相当于区间max,min。

         那么单调队列解决。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define maxn 2050
    #define inf 2000000
    using namespace std;
    int n,m,k,no[maxn][maxn],so[maxn][maxn],map[maxn][maxn],x[maxn],y[maxn],ans[maxn],dp[maxn][maxn];
    int q1[maxn],h1,t1,q2[maxn],h2,t2;
    char s[maxn];
    void get_table()
    {
        for (int j=1;j<=m;j++)
        {
            int ret=0;
            for (int i=1;i<=n;i++)
            {
                no[i][j]=ret;
                if (map[i][j]) ret=i;
            }
            ret=n+1;
            for (int i=n;i>=1;i--)
            {
                so[i][j]=ret;
                if (map[i][j]) ret=i;
            }
        }
    }
    void dp_()
    {
        for (int i=1;i<=n;i++)
            for (int j=1;j<=m;j++)
            {
                if (!map[i][j]) dp[i][j]=min(dp[i-1][j-1],min(dp[i-1][j],dp[i][j-1]))+1;
                else dp[i][j]=0;
                ans[k]=max(ans[k],dp[i][j]);
            }
    }
    bool check(int l,int x,int y)
    {
        int lb=-1,rb=inf,ret=0;
        for (int i=y-1;i>=0;i--) if (map[x][i]) {lb=i+1;break;}
        for (int i=y+1;i<=m+1;i++) if (map[x][i]) {rb=i-1;break;}
        int left=max(lb,y-l+1),right=min(y,rb-l+1);h1=h2=1;t1=t2=0;
        for (int i=left;i<=left+l-1;i++)
        {
            while (h1<=t1 && no[x][i]>=no[x][q1[t1]]) t1--;q1[++t1]=i;
            while (h2<=t2 && so[x][i]<=so[x][q2[t2]]) t2--;q2[++t2]=i; 
        }
        for (int i=left;i<=right;i++)
        {
            ret=max(ret,so[x][q2[h2]]-no[x][q1[h1]]-1);
            while (h1<=t1 && q1[h1]<=i) h1++;
            while (h1<=t1 && no[x][i+l]>=no[x][q1[t1]]) t1--;q1[++t1]=i+l;
            while (h2<=t2 && q2[h2]<=i) h2++;
            while (h2<=t2 && so[x][i+l]<=so[x][q2[t2]]) t2--;q2[++t2]=i+l;
        }
        return ret>=l;
    }
    void ask()
    {
        for (int i=k;i>=2;i--)
        { 
            map[x[i]][y[i]]=0;
            int ret=0;
            for (int j=1;j<=n;j++)
            {
                no[j][y[i]]=ret;
                if (map[j][y[i]]) ret=j;    
            } 
            ret=n+1;
            for (int j=n;j>=1;j--)
            {
                so[j][y[i]]=ret;
                if (map[j][y[i]]) ret=j;
            }
            int p=ans[i]+1;
            while (check(p,x[i],y[i]) && p<=min(n,m))
                p++;
            ans[i-1]=p-1;
        }
    }
    int main()
    {
        scanf("%d%d%d",&n,&m,&k);
        for (int i=1;i<=n;i++)
        {
            scanf("%s",s+1);
            for (int j=1;j<=m;j++)
            {
                if (s[j]=='X') map[i][j]=1;
                else map[i][j]=0;
            }
        }
        for (int i=1;i<=n;i++) map[i][0]=map[i][m+1]=1;
        for (int i=1;i<=m;i++) map[0][i]=map[n+1][i]=1;
        for (int i=1;i<=k;i++)
        {
            scanf("%d%d",&x[i],&y[i]);
            map[x[i]][y[i]]=1;
        }
        get_table();
        dp_();
        ask();
        for (int i=1;i<=k;i++) printf("%d
    ",ans[i]);
        return 0;
    }

    C.

      和上一场的C有什么区别吗。。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #define maxn 100500
    using namespace std;
    long long n,prime[maxn],tot=0,w[maxn][60],ans=0,mn[maxn],f,kr=0;
    bool vis[maxn];
    void get_table()
    {
        for (long long i=2;i<=maxn-500;i++)
        {
            if (!vis[i]) prime[++tot]=mn[i]=i;
            for (long long j=1;i*prime[j]<=maxn-500;j++)
            {
                vis[i*prime[j]]=true;mn[i*prime[j]]=prime[j];
                if (i%prime[j]) continue;break;
            }
        }
        for (long long i=2;i<=maxn-500;i++)
        {
            long long ret=-1,x=i;
            while (x!=1)
            {
                if (mn[x]!=ret) {ret=mn[x];w[i][0]++;w[i][w[i][0]]=mn[x];}
                x/=mn[x];
            }
        }
    }
    void dfs(long long now,long long top,long long ret,long long val,long long n)
    {
        if (now==w[top][0]+1)
        {
            if (!ret) return;
            if (ret&1) kr+=n/val;else kr-=n/val;
            return;
        }
        dfs(now+1,top,ret,val,n);
        dfs(now+1,top,ret+1,val*w[top][now],n);
    }
    void ask(long long n,long long val) {kr=0;dfs(1,val,0,1,n);}
    int main()
    {
        scanf("%lld",&n);
        get_table();
        long long top=sqrt(n);
        for (long long i=2;i<=top;i++)
        {
            ask(n/i,i);ans+=(n/i)-kr;
            ask(i,i);ans-=i-kr;
        }
        printf("%lld
    ",ans);
        return 0;
    }
  • 相关阅读:
    程序员的双11:3723亿,你贡献了几分力?
    程序员国企1周上班5小时?国企VS私企,应该如何选择?
    C++没有"垃圾回收"功能?智能指针,实现C++的内存管理
    【C++学习笔记】什么是C++STL?掌握C++ STL的核心很重要!
    都要2021年了,现代C++有什么值得我们学习的?
    解析:C++如何实现简单的学生管理系统(源码分享)
    程序员过高工资导致加班?应该降低程序员工资?网友:放过其他苦逼的程序员吧
    结对-结对编程项目作业名称-需求分析
    使用对话框模板创建一个InputBox()在C + +
    选择图标
  • 原文地址:https://www.cnblogs.com/ziliuziliu/p/6411333.html
Copyright © 2011-2022 走看看