• NOIP2015 Revenge


    辣鸡出题人,毁我比赛,颓我精神,耗我钱财,废我青春。

    去年成绩惨不忍睹就不说了...好像是100+80+0+100+50+60。

    大概列一下算法。

    幻方:模拟

    #include <iostream>
    #include <stdio.h>
    #include <stdlib.h>
    #include <memory.h>
    using namespace std;
    int n,mat[50][50],px,py;
    #define FO(s) {freopen(#s".in","r",stdin);freopen(#s".out","w",stdout);}
    int main()
    {
        cin>>n;
        memset(mat,0,sizeof(mat));
        px=1; py=(n+1)/2;
        mat[px][py]=1;
        //By zzq
        for(int i=2;i<=n*n;i++)
        {
            if(px==1&&py!=n)
            {
                px=n; ++py; mat[px][py]=i;
            }
            else if(py==n&&px!=1)
            {
                --px; py=1; mat[px][py]=i;
            }
            else if(px==1&&py==n)
            {
                ++px; mat[px][py]=i;
            }
            else
            {
                if(!mat[px-1][py+1])
                {
                    --px; ++py; mat[px][py]=i;
                }
                else
                {
                    ++px; mat[px][py]=i;
                }
            }
        }
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=n;j++)
            {
                printf("%d",mat[i][j]);
                if(j!=n) putchar(' ');
            }
            putchar('
    ');
        }
    }

    信息传递:tarjan/鬼畜dfs(各种写丑写成平方的都有80)

    #include <iostream>
    #include <stdio.h>
    #include <stdlib.h>
    #include <stack>
    using namespace std;
    //tarjan!
    int n,t[233333],low[233333],dfn[233333],cur=0,siz=2000000000;
    bool instack[233333],ved[233333];
    int ss[233333],sn=0;
    void tarjan(int s)
    {
        dfn[s]=low[s]=++cur; ss[++sn]=s;
        instack[s]=1; ved[s]=1;
        if(instack[t[s]]) low[s]=min(low[s],dfn[t[s]]);
        else if(!dfn[t[s]])
        {
            tarjan(t[s]);
            low[s]=min(low[s],low[t[s]]);
        }
        if(dfn[s]==low[s])
        {
            int cs=0;
            while(1)
            {
                ++cs;
                instack[ss[sn]]=0;
                int t=ss[sn--];
                if(t==s) break;
            }
            if(cs!=1) siz=min(siz,cs);
        }
    } 
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++) scanf("%d",t+i);
        for(int i=1;i<=n;i++) if(!ved[i]) tarjan(i);
        printf("%d
    ",siz);
    }

    斗地主:欧洲人

    跳石头:二分

    #include <iostream>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <set>
    using namespace std;
    int D[233333],L,n,m;
    bool ok(int x)
    {
        int cp=0,del=0;
        for(int i=1;i<=n;i++)
        {
            if(D[i]-cp<x)
            {
                del++; continue;
            }
            cp=D[i];
        }
        if(L-cp<x) del++;
        return del<=m;
    }
    int main()
    {
        scanf("%d%d%d",&L,&n,&m);
        for(int i=1;i<=n;i++) scanf("%d",D+i);
        int l=0,r=L;
        while(l<r)
        {
            int mid=(l+r+1)>>1;
            if(ok(mid)) l=mid; else r=mid-1;
        }
        printf("%d
    ",l);
    }

    子串:dp

    dp[k][i][j]表示最优情况下使用k个子串,用了A串第i个构成B串前j个的方案数。

    dp[k][i][j]=qzh[k-1][i-1][j-1] (注意这个前缀和只有第二维)

    如果a[i-1]=b[j-1],那么dp[k][i][j]+=dp[k][i-1][j-1]

    考场上不知道是哪里抽风了顺手多记了一维= =

    似乎要随便滚动一下

    #include <iostream>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <algorithm>
    using namespace std;
    int MOD=1000000007;
    int n,m,w,qzh[2][1005][205],dp[2][1005][205];
    char a[233333],b[233333];
    int main()
    {
        scanf("%d%d%d%s%s",&n,&m,&w,a+1,b+1);
        dp[0][0][0]=1;
        for(int i=0;i<=n;i++) qzh[0][i][0]=1;
        for(int k=1;k<=w;k++)
        {
            for(int i=0;i<=n;i++)
            {
                for(int j=0;j<=m;j++) qzh[k&1][i][j]=dp[k&1][i][j]=0;
            }
            for(int i=1;i<=n;i++)
            {
                for(int j=1;j<=m;j++)
                {
                    if(a[i]!=b[j]) continue;
                    int&cp=dp[k&1][i][j];
                    cp=qzh[(k-1)&1][i-1][j-1];
                    if(a[i-1]==b[j-1]) cp=(cp+dp[k&1][i-1][j-1])%MOD;
                }
                for(int j=0;j<=m;j++) qzh[k&1][i][j]=(qzh[k&1][i-1][j]+dp[k&1][i][j])%MOD;
            }
        }
        printf("%d
    ",qzh[w&1][n][m]);
    }

    运输计划:乱搞

    考虑二分答案,对于每一个超过限制的,我们必然要在其上选择一条边删去,且该条边权>=实际值-二分值。

    那么我们暴力路径+1,再暴力for一下每一条边即可。

    什么?怎么+1?前缀和!

    #include <iostream>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <algorithm>
    using namespace std;
    #define SZ 666666
    #define P 20
    typedef pair<int,int> pii;
    int n,m,fa[SZ],fv[SZ],vc[SZ],dep[SZ],fst[SZ],vb[SZ],nxt[SZ],M=0,qa[SZ],qb[SZ],ql[SZ],ea[SZ],eb[SZ],ec[SZ],reald[SZ];
    void ad_de(int a,int b,int c) {++M; nxt[M]=fst[a]; fst[a]=M; vb[M]=b; vc[M]=c;}
    int cc=0,app[SZ],bs[SZ],up[SZ][P],cx[SZ],c2=0;
    pii pp[SZ],minn[SZ][P];
    void dfs(int x)
    {
        ++cc; app[x]=cc; pp[cc]=pii(dep[x],x); cx[++c2]=x;
        for(int e=fst[x];e;e=nxt[e])
        {
            int b=vb[e]; if(b==fa[x]) continue;
            fa[b]=x; fv[b]=fv[x]+vc[e]; dep[b]=dep[x]+1;
            dfs(b); pp[++cc]=pii(dep[x],x);
        }
    }
    void build()
    {
        for(int i=1;i<=n;i++) up[i][0]=fa[i];
        for(int p=1;p<P;p++)
        {
            for(int i=1;i<=n;i++)
            {
                if(up[i][p-1]) up[i][p]=up[up[i][p-1]][p-1];
            }
        }
        for(int i=1;i<=cc;i++) minn[i][0]=pp[i];
        for(int i=1;i<=cc;i++)
        {
            int g=0;
            while((1<<g)<=i) ++g;
            bs[i]=g-1;
        }
        for(int p=1;p<P;p++)
        {
            for(int i=1;i<=cc;i++)
            {
                if(i+(1<<p)-1>cc) break;
                minn[i][p]=min(minn[i][p-1],minn[i+(1<<(p-1))][p-1]);
            }
        }
    }
    int jump(int x,int d)
    {
        for(int i=P-1;i>=0;i--)
        {
            if(up[x][i]&&dep[up[x][i]]>=d) x=up[x][i];
        }
        return x;
    }
    int lca(int a,int b)
    {
        a=app[a]; b=app[b];
        if(a>b) swap(a,b);
        int l2=bs[b-a+1];
        return min(minn[a][l2],minn[b-(1<<l2)+1][l2]).second;
    }
    int dis(int a,int b,int l)
    {
        return fv[a]+fv[b]-fv[l]*2;
    }
    int pv[SZ],cv[SZ];
    bool ok(int x)
    {
        int cnt=0,need=0;
        for(int i=1;i<=n;i++) pv[i]=0;
        for(int i=1;i<=m;i++)
        {
            if(reald[i]<=x) continue;
            ++cnt; pv[ql[i]]-=2; pv[qa[i]]++; pv[qb[i]]++;
            need=max(need,reald[i]-x);
        }
        if(!cnt) return 1;
        for(int i=n;i>=1;i--) pv[fa[cx[i]]]+=pv[cx[i]];
        for(int i=1;i<n;i++)
        {
            if(ec[i]<need) continue;
            if(pv[eb[i]]!=cnt) continue;
            return 1;
        }
        return 0;
    }
    #define BUFSIZE 300000
    namespace fib {char b[BUFSIZE]={},*f=b;}
    #define gc ((*fib::f)?(*(fib::f++)):(fgets(fib::b,sizeof(fib::b),stdin)?(fib::f=fib::b,*(fib::f++)):-1))
    int g_i()
    {
        int tmp=0; bool fu=0; char s;
        while(s=gc,s!='-'&&(s<'0'||s>'9')) ;
        if(s=='-') fu=1; else tmp=s-'0';
        while(s=gc,s>='0'&&s<='9') tmp=tmp*10+s-'0';
        if(fu) return -tmp; else return tmp;
    }
    #define gi g_i()
    namespace fob {char b[BUFSIZE]={},*f=b,*g=b+BUFSIZE-2;}
    #define pob (fwrite(fob::b,sizeof(char),fob::f-fob::b,stdout),fob::f=fob::b,0)
    #define pc(x) (*(fob::f++)=(x),(fob::f==fob::g)?pob:0)
    struct foce {~foce() {pob; fflush(stdout);}} _foce;
    namespace ib {char b[100];}
    inline void pint(int x)
    {
        if(x==0) {pc(48); return;}
        if(x<0) {pc('-'); x=-x;}
        char *s=ib::b;
        while(x) *(++s)=x%10, x/=10;
        while(s!=ib::b) pc((*(s--))+48);
    }
    int main()
    {
        n=gi,m=gi;
        for(int i=1;i<n;i++)
        {
            int a=gi, b=gi, c=gi;
            ea[i]=a; eb[i]=b; ec[i]=c;
            ad_de(a,b,c); ad_de(b,a,c);
        }
        for(int i=1;i<=m;i++) qa[i]=gi, qb[i]=gi;
        dfs(1); build();
        int l=0,r=0;
        for(int i=1;i<=m;i++) ql[i]=lca(qa[i],qb[i]), reald[i]=dis(qa[i],qb[i],ql[i]), r=max(r,reald[i]);
        for(int i=1;i<n;i++) if(dep[ea[i]]>dep[eb[i]]) swap(ea[i],eb[i]);
        while(l<r)
        {
            int mid=l+r>>1;
            if(ok(mid)) r=mid; else l=mid+1;
        }
        printf("%d
    ",l);
    }

    然后我们只要兹磁O(1) lca就行了。可能需要卡常~(我卡了三发才过)

  • 相关阅读:
    java (取文本中间)字符串之间的文本
    Mysql数据库中text还是不够
    java读取网页内容
    controller to controller
    农历类
    java.lang.RuntimeException: com.google.inject.CreationException: Unable to create injector, see the following errors
    Java中List集合去除重复数据的方法
    idea启动tomcat的中文乱码问题
    idea局域网调试 can accept external connection不可勾选
    Mysql JDBC Url参数说明useUnicode=true&characterEncoding=UTF-8
  • 原文地址:https://www.cnblogs.com/zzqsblog/p/5625293.html
Copyright © 2020-2023  润新知