zoukankan      html  css  js  c++  java
  • 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就行了。可能需要卡常~(我卡了三发才过)

  • 相关阅读:
    SQL Server Audit监控触发器状态
    SQL Server 数据变更时间戳(timestamp)在复制中的运用
    SQL Server 更改跟踪(Chang Tracking)监控表数据
    SQL Server 变更数据捕获(CDC)监控表数据
    SQL Server 事件通知(Event notifications)
    SQL Server 堆表行存储大小(Record Size)
    SQL Server DDL触发器运用
    SQL Server 默认跟踪(Default Trace)
    SQL Server 创建数据库邮件
    SQL Server 跨网段(跨机房)FTP复制
  • 原文地址:https://www.cnblogs.com/zzqsblog/p/5625293.html
Copyright © 2011-2022 走看看