zoukankan      html  css  js  c++  java
  • [4.14校内训练赛by hzwer]

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


    hzwer又出丧题虐人 4道noi....        很奇怪 每次黄学长出题总有一题我做过了。

    嗯题目你们自己看看呗 好难解释

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

    A.[bzoj1565][NOI2009]植物大战僵尸

    这道题其实挺好想的。nm比较小,考虑最小割,假设割到S表示吃,割到T表示不吃

    那么能源小于0的,从S向他连边,流量是负的能源,

    能源大于0的,从它向T连边,流量是能源,同时答案加上能源,

    然后对于每一个限制条件,都连INF的边 最后最小割。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define S 0
    #define T 601
    #define INF 2000000000
    #define num(x,y) ((x-1)*m+y)
    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 head[T+5],head2[T+5],c[T+5],d[T+5],cnt=T*T*5,tcnt=0,n,m,ans=0,q[T+5],top,s[T+5],in[T+5];
    struct edge{int to,next,w;}e[5000000];
    bool b[T+5];
    
    void ins(int f,int t){e[++tcnt]=(edge){t,head2[f],0};head2[f]=tcnt;in[t]++;}
    void ins(int f,int t,int w)
    {
        e[++cnt]=(edge){t,head[f],w};head[f]=cnt;
        e[++cnt]=(edge){f,head[t],0};head[t]=cnt;
    }
    
    void topsort(int x)
    {
        q[top=1]=x;
        for(int i=1;i<=top;i++)
        {
            if(x=q[i])
            b[x]=1,s[x]>=0?(ans+=s[x],ins(x,T,s[x]),0)
                             :(ins(S,x,-s[x]),0);    
            for(int j=head2[x];j;j=e[j].next)
                if(!--in[e[j].to]) q[++top]=e[j].to;
        }
    
        for(int i=1;i<=n*m;i++) if(b[i])
            for(int j=head2[i];j;j=e[j].next) if(b[e[j].to])
                ins(i,e[j].to,INF);    
    }
    
    int dfs(int x,int f)
    {
        if(x==T)return f;
        int used=0;
        for(int&i=c[x];i;i=e[i].next)
            if(e[i].w&&d[e[i].to]==d[x]+1)
            {
                int w=dfs(e[i].to,min(f-used,e[i].w));
                used+=w;e[i].w-=w;e[i^1].w+=w;
                if(used==f)return f;
            }
        return d[x]=-1,used;
    }
    
    bool bfs()
    {
        memset(d,0,sizeof(d));int i,j;
        for(d[q[top=i=1]=S]=1;i<=top;i++)
            for(int j=c[q[i]]=head[q[i]];j;j=e[j].next)
                if(e[j].w&&!d[e[j].to])
                    d[q[++top]=e[j].to]=d[q[i]]+1;
        return d[T];
    }
    
    int main()
    {
          n=read();m=read();
          for(int i=1;i<=n;i++)
              for(int j=1;j<=m;j++)
              {
                  if(j>1) ins(num(i,j),num(i,j-1));
                s[num(i,j)]=read();
                for(int k=read();k;k--) 
                {
                    int x=read()+1,y=read()+1;
                    ins(num(i,j),num(x,y));
                }
            }
          for(int i=1;i<=n;i++) ins(0,num(i,m));    
          topsort(0);
          while(bfs()) ans-=dfs(S,INF);
          cout<<ans;
        return 0;
    }

    B.阿狸的打字机 戳这里

    C.[bzoj1499][NOI2005]瑰丽华尔兹

    题解:很容易想到O(nmk)dp,然后我们每一次的更新都只能从一个方向转移,用一个单调队列维护一下

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define pa pair<int,int>
    #define mp(x,y) make_pair(x,y)
    #define MN 200
    #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;
    }
     
    int f[MN+5][MN+5][MN+5],T[MN+5],dir[MN+5],n,m,x,y,k;
    char st[MN+5][MN+5];
    struct MyQueue
    {
        int top,tail;pa s[MN+5];
        void clear(int x){top=tail=0;s[top]=mp(x,-INF);}
        void ins(int x,int from)
        {
            while(s[top].second<x&&top>=tail) --top;
            s[++top]=mp(from,x);
        }
        int get(int t)
        {
            while(s[tail].first<t) ++tail;
            return s[tail].second;
        }
    }q;
     
    int main()
    {
        memset(f,128,sizeof(f)); q.clear(0);
        n=read();m=read();x=read();y=read();k=read();
        f[0][x][y]=0;
        for(int i=1;i<=n;i++) scanf("%s",st[i]+1);
        for(int i=1;i<=k;i++)
        {
            int x=read(),y=read();
            T[i]=y-x+1;dir[i]=read();
        }
        for(int t=1;t<=k;t++)
        {
            for(int i=1;i<=n;i++)
                for(int j=1;j<=m;j++)
                    f[t][i][j]=max(f[t][i][j],f[t-1][i][j]);
            if(dir[t]==1)
                for(int i=1;i<=m;i++,q.clear(0))
                    for(int j=n;j;j--)
                        if(st[j][i]!='x')
                            f[t][j][i]=max(f[t][j][i],q.get(n+1-j-T[t])-j),q.ins(f[t-1][j][i]+j,n+1-j);
                        else q.clear(n+1-j);
            if(dir[t]==2)
                for(int i=1;i<=m;i++,q.clear(0))
                    for(int j=1;j<=n;j++)
                        if(st[j][i]!='x')
                            f[t][j][i]=max(f[t][j][i],q.get(j-T[t])+j),q.ins(f[t-1][j][i]-j,j);
                        else q.clear(j);
            if(dir[t]==3)
                for(int i=1;i<=n;i++,q.clear(0))
                    for(int j=m;j;j--)
                        if(st[i][j]!='x')
                            f[t][i][j]=max(f[t][i][j],q.get(m+1-j-T[t])-j),q.ins(f[t-1][i][j]+j,m+1-j);
                        else q.clear(m+1-j);
            if(dir[t]==4)
                for(int i=1;i<=n;i++,q.clear(0))
                    for(int j=1;j<=m;j++)
                        if(st[i][j]!='x')
                            f[t][i][j]=max(f[t][i][j],q.get(j-T[t])+j),q.ins(f[t-1][i][j]-j,j);
                        else q.clear(j);
        }
        int ans=0;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                ans=max(ans,f[k][i][j]);
        cout<<ans;
        return 0;
    }
     
    

    D.[bzoj3670][Noi2014]动物园
    自己yy了一下,发现num[i]就是在i/2之前的fail节点的个数。

    可以假装用自己这个串匹配自己,然后到了第i个点的时候突然不对了(别问我为什么不对),那么我跳到的fail节点一定既是前缀又是现在的后缀,因为我在匹配自己呢(雾)

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define MN 1000000
    #define mod 1000000007
    using namespace std;
    bool b[MN+5];
    int fail[MN+5],num[MN+5],ans=1;
    char st[MN+5];
    int main()
    {
        num[1]=1;int T;
        for(cin>>T;T;T--)
        {
            scanf("%s",st+1);ans=1;
            memset(b,0,sizeof(b));
            for(int i=2,j=0;st[i];i++)
            {
                while(j&&st[j+1]!=st[i])j=fail[j];
                if(st[j+1]==st[i]) ++j; 
                fail[i]=j;num[i]=num[j]+1;
            }
            for(int i=2,j=0;st[i];i++)
            {
                while(j&&((j+1)*2>i||st[j+1]!=st[i]))j=fail[j];
                if(st[j+1]==st[i]) ++j; 
                ans=1LL*ans*(num[j]+1)%mod;
            }
            printf("%d
    ",ans);
        }
        return 0;
    }
     
    
  • 相关阅读:
    Cmder安装和设置
    php7.x版本的新特性
    【Luogu】P4916 [MtOI2018]魔力环 题解
    Codeforces 1530E Minimax 题解
    昭阳E42-80 屏幕不亮,风扇狂转
    iPad宽高像素值
    关于UIView的autoresizingMask属性的研究
    判断单链表中是否存在环及查找环的入口点
    网络编程
    事件响应者链的工作原理
  • 原文地址:https://www.cnblogs.com/FallDream/p/hzwer414.html
Copyright © 2011-2022 走看看