• 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;
    }
  • 相关阅读:
    关于返回上一页功能
    Mybatis Update statement Date null
    SQLite reset password
    Bootstrap Validator使用特性,动态(Dynamic)添加的input的验证问题
    Eclipse使用Maven2的一次环境清理记录
    Server Tomcat v7.0 Server at localhost failed to start
    PowerShell一例
    Server Tomcat v7.0 Server at libra failed to start
    商标注册英语
    A glance for agile method
  • 原文地址:https://www.cnblogs.com/ziliuziliu/p/6411333.html
Copyright © 2020-2023  润新知