• WC2016自测


    挑战NPC

    原题链接
    爆搜20分,贪心10分,网络流30分

    //挑战NPC
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    inline char gc()
    {
        static char now[1<<16],*S,*T;
        if(S==T) {T=(S=now)+fread(now,1,1<<16,stdin); if(S==T) return EOF;}
        return *S++;
    }
    inline int read()
    {
        int x=0; char ch=gc();
        while(ch<'0'||'9'<ch) ch=gc();
        while('0'<=ch&&ch<='9') x=x*10+ch-'0',ch=gc();
        return x;
    }
    int const N=420;
    int const INF=0x7FFFFFFF;
    int n,m,e;
    int edCnt,h[N];
    struct edge{int v,c,nxt;} ed[N*N];
    void edAdd(int u,int v,int c)
    {
        edCnt++; ed[edCnt].v=v,ed[edCnt].c=c,ed[edCnt].nxt=h[u],h[u]=edCnt;
        edCnt++; ed[edCnt].v=u,ed[edCnt].c=0,ed[edCnt].nxt=h[v],h[v]=edCnt;
    }
    int ans1,link1[N],cnt1[N],link[N];
    void check()
    {
        memset(cnt1,0,sizeof cnt1);
        int res=0;
        for(int i=1;i<=n;i++) cnt1[link[i]]++;
        for(int i=1;i<=m;i++) if(cnt1[i]<=1) res++; else if(cnt1[i]>3) return;
        if(res>ans1) ans1=res,memcpy(link1,link,sizeof link);
    }
    void dfs(int u)
    {
        if(u>n) check();
        for(int i=h[u];i;i=ed[i].nxt) link[u]=ed[i].v-n,dfs(u+1);
    }
    void work1()
    {
        ans1=-1; dfs(1);
        printf("%d
    ",ans1);
        for(int i=1;i<=n;i++) printf("%d ",link1[i]);
        printf("
    ");
    }
    void work2()
    {
        int ans2=m; if(n>m) ans2-=(n-m+1)/2;
        printf("%d
    ",ans2);
        for(int i=1;i<=ans2&&i<=n;i++) printf("%d ",i);
        for(int i=1;i<=n-ans2;i++) printf("%d ",ans2+(i+2)/3);
        printf("
    ");
    }
    int s,t;
    int dpt[N]; int op,cl,q[N];
    bool bfs()
    {
        memset(dpt,0,sizeof dpt);
        op=cl=0; dpt[q[++cl]=s]=1;
        while(op<cl)
        {
            int u=q[++op]; if(u==t) break;
            for(int i=h[u];i;i=ed[i].nxt)
            {
                int v=ed[i].v,c=ed[i].c;
                if(!dpt[v]&&c) dpt[q[++cl]=v]=dpt[u]+1;
            }
        }
        return dpt[t];
    }
    int fill(int u,int in)
    {
        if(u==t||in==0) return in;
        int out=0;
        for(int i=h[u];i;i=ed[i].nxt)
        {
            int v=ed[i].v,c=ed[i].c;
            if(dpt[v]!=dpt[u]+1||!c) continue;
            int fl=fill(v,min(in-out,c));
            if(fl==0) dpt[v]=0;
            else out+=fl,ed[i].c-=fl,ed[i^1].c+=fl;
            if(in==out) return out;
        }
        return out;
    }
    int Dinic()
    {
        int res=0;
        while(bfs()) res+=fill(s,INF);
        return res;
    }
    void work3()
    {
        s=0,t=n+m+1;
        for(int i=1;i<=n;i++) edAdd(s,i,1);
        int edCnt1=edCnt+1;
        for(int i=1;i<=m;i++) edAdd(n+i,t,1);
        int flow=Dinic(),ans3=m;
        if(flow!=n)
        {
            for(int i=2;i<=edCnt1;i++) ed[i].c=(i&1)?0:1;
            for(int i=edCnt1;i<=edCnt;i++) ed[i].c=(i&1)?0:3;
            Dinic(); ans3=0;
            for(int i=h[t];i;i=ed[i].nxt) if(ed[i].c<=1) ans3++;
        }
        printf("%d
    ",ans3);
        for(int u=1;u<=n;u++)
            for(int i=h[u];i;i=ed[i].nxt)
                if(ed[i].c==0&&ed[i].v!=s) {printf("%d ",ed[i].v-n); break;}
        printf("
    "); return;
    }
    int main()
    {
        freopen("npc.in","r",stdin);
        int task=read();
        while(task--)
        {
    
        n=read(),m=read(),e=read();
        edCnt=1; memset(h,0,sizeof h);
        for(int i=1;i<=e;i++) {int u=read(),v=read(); edAdd(u,v+n,1);}
        if(e<=25) work1();
        else if(e==n*m) work2();
        else work3();
    
        }
        return 0;
    }

    论战捆竹竿

    原题链接
    竹竿之间的捆绑可以看做在字符串后面续一段,这要求求出所有相同的前缀与后缀。转化为了给出若干个正整数,求[1,w]中有多少个数能被这些数的和表达出来。

    //论战捆竹竿
    #include <cstdio>
    #include <cstring>
    int const N=5e5+10;
    int n,lim; char s[N];
    int sa[N],rank[N<<1],h[N];
    int cnt[N],tmp[N],rank1[N];
    int min(int x,int y) {return x<y?x:y;}
    bool add[N],f[N];
    int tCnt,t[N];
    int main()
    {
        freopen("jie.in","r",stdin);
        int task; scanf("%d",&task);
        while(task--)
        {
    
        scanf("%d%d",&n,&lim);
        scanf("%s",s+1);
        if(lim<n) {printf("0
    "); continue;}
        memset(cnt,0,sizeof cnt); memset(rank,0,sizeof rank);
        for(int i=1;i<=n;i++) cnt[s[i]]=1;
        for(int i='a';i<='z';i++) cnt[i]+=cnt[i-1];
        for(int i=1;i<=n;i++) rank[i]=cnt[s[i]];
        int k=0;
        for(int L=1;k<n;L<<=1)
        {
            memset(cnt,0,sizeof cnt);
            for(int i=1;i<=n;i++) cnt[rank[i+L]]++;
            for(int i=1;i<=n;i++) cnt[i]+=cnt[i-1];
            for(int i=n;i>=1;i--) tmp[cnt[rank[i+L]]--]=i;
            memset(cnt,0,sizeof cnt);
            for(int i=1;i<=n;i++) cnt[rank[tmp[i]]]++;
            for(int i=1;i<=n;i++) cnt[i]+=cnt[i-1];
            for(int i=n;i>=1;i--) sa[cnt[rank[tmp[i]]]--]=tmp[i];
            k=0; memcpy(rank1,rank,sizeof rank1);
            for(int i=1;i<=n;i++)
            {
                if(rank1[sa[i]]!=rank1[sa[i-1]]||rank1[sa[i]+L]!=rank1[sa[i-1]+L]) k++;
                rank[sa[i]]=k;
            }
        }
        k=0; memset(h,0,sizeof h);
        for(int i=1;i<=n;i++)
        {
            if(--k<0) k=0;
            if(rank[i]==1) {h[1]=0; continue;}
            while(s[i+k]==s[sa[rank[i]-1]+k]) k++;
            h[rank[i]]=k;
        }
        int len=N; memset(add,false,sizeof add);
        for(int i=rank[1]-1;i>=1;i--)
            if((len=min(len,h[i+1]))==n-sa[i]+1) add[sa[i]-1]=true;
        len=N;
        for(int i=rank[1]+1;i<=n;i++)
            if((len=min(len,h[i]))==n-sa[i]+1) add[sa[i]-1]=true;
        add[n]=true;
        for(int i=1;i<=n;i++)
            if(add[i]) for(int j=i<<1;j<=n;j+=i) add[j]=false;
        tCnt=0;
        for(int i=1;i<=n;i++) if(add[i]) t[++tCnt]=i;
        memset(f,false,sizeof f); f[n]=true;
        for(int i=n;i<=lim;i++)
            if(f[i]) for(int j=1;j<=tCnt;j++) f[i+t[j]]=true;
        int ans=0;
        for(int i=n;i<=lim;i++) if(f[i]) ans++;
        printf("%d
    ",ans);
        for(int i=1;i<=tCnt;i++) printf("%d ",t[i]);
    
        }
        return 0;
    }

    鏖战表达式

    原题链接
    友情提示这字念鏖(áo)。并不会做。
    k=1可以用可持久化平衡树搞?可惜我不会。

  • 相关阅读:
    pip解决超时问题(timeout)
    Docker commit使用
    Docker基本命令汇总
    python redis模块详解
    python异步编程之asyncio(百万并发)
    VideoJS 与 Framework7 中 fastclick 冲突问题
    Linux 下解决安装多个node冲突的问题(重新安装node)
    git push multiple repo
    webpack import windows case sensitive
    一键切图 PS 动作 【收藏】
  • 原文地址:https://www.cnblogs.com/VisJiao/p/8485741.html
Copyright © 2020-2023  润新知