• NOIP模拟赛10


    T1 [HAOI2010]软件安装

    https://daniu.luogu.org/problem/show?pid=2515

    树上背包,如果有i必须有j,j作为i的父节点

    O(nm²)

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define N 101
    #define M 501
    using namespace std;
    int y[N],h[N],x[N];
    int dfn[N],low[N],st[N],top,tot;
    bool vis[N];
    int cnt,ny[N],nh[N],col[N];
    int dp[N][M],m;
    int to[M],nxt[M],front[N];
    int to2[M],nxt2[M],front2[M];
    void read(int &x)
    {
        x=0; char c=getchar();
        while(!isdigit(c)) c=getchar();
        while(isdigit(c)) { x=x*10+c-'0'; c=getchar(); }
    }
    void add(int u,int v)
    {
        to[++tot]=v; nxt[tot]=front[u]; front[u]=tot;
    }
    void add2(int u,int v)
    {
        to2[++tot]=v; nxt2[tot]=front2[u]; front2[u]=tot;
    }
    void tarjan(int u)
    {
        dfn[u]=low[u]=++tot;
        vis[u]=true;
        st[++top]=u;
        if(x[u]) 
        {
            if(!dfn[x[u]]) tarjan(x[u]),low[u]=min(low[u],low[x[u]]);
            else if(vis[x[u]]) low[u]=min(low[u],dfn[x[u]]);
        }
        if(dfn[u]==low[u])
        {
            cnt++;
            while(st[top]!=u)
            {
                ny[cnt]+=y[st[top]];
                nh[cnt]+=h[st[top]];
                vis[st[top]]=false;
                col[st[top]]=cnt;
                top--;
            }
            ny[cnt]+=y[u];
            nh[cnt]+=h[u];
            vis[u]=false;
            col[u]=cnt;
            top--;
        }
    }
    void dfs(int now)
    {
        for(int i=ny[now];i<=m;i++) dp[now][i]=nh[now];
        for(int i=front2[now];i;i=nxt2[i])
            {
                dfs(to2[i]);
                for(int j=m;j>=ny[now];j--)
                    for(int k=0;k<=j-ny[now];k++)
                        dp[now][j]=max(dp[now][j],dp[now][j-k]+dp[to2[i]][k]);
            }
    }
    int main()
    {
        int n;
        read(n); read(m);
        for(int i=1;i<=n;i++) read(y[i]);
        for(int i=1;i<=n;i++) read(h[i]);
        for(int i=1;i<=n;i++) 
        {
            read(x[i]);
            add(x[i],i);
         } 
         tot=0;
        for(int i=1;i<=n;i++)
            if(!dfn[i]) tarjan(i);
        memset(vis,false,sizeof(vis));    
        tot=0;
        for(int i=1;i<=n;i++)
            if(col[i]!=col[x[i]])
                add2(col[x[i]],col[i]),vis[col[i]]=true;
        for(int i=1;i<=cnt;i++)
            if(!vis[i]) add2(0,i);
        dfs(0);
        printf("%d",dp[0][m]);
    }
    View Code

    可以优化值O(nm),即每次都将要处理的子树和根节点看做一个整体

    在dfs子树前,将根节点的值赋值给子节点

    具体参考XCH的《浅谈几类背包问题》

    https://wenku.baidu.com/view/d59b42fe04a1b0717fd5dd72.html

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    const int maxn=10005,maxm=2505;
    struct edge
    {
        int u,v;
    };
    struct edge Edge[maxn];
    int bel[maxn],n,m,col,hi[maxn],yi[maxn],head[maxn],tag,dp[maxn][maxm];
    int E[maxn<<1],V[maxn<<1],cnt,ci[maxn],vi[maxn],dfn[maxn],low[maxn];
    int sta[maxn],top,num;
    bool vis[maxn];
    inline void in(int &now)
    {
        char Cget;now=0;while((Cget=getchar())>'9'||Cget<'0');
        while(Cget>='0'&&Cget<='9')now=now*10+Cget-'0',Cget=getchar();
    }
    void tarjan(int now)
    {
        dfn[now]=low[now]=++tag,sta[++top]=now;
        for(int i=head[now];i;i=E[i])
            if(!bel[V[i]])
                if(dfn[V[i]]) low[now]=min(low[now],dfn[V[i]]);
                else tarjan(V[i]),low[now]=min(low[now],low[V[i]]);
        if(low[now]==dfn[now])
        {
            col++;
            while(sta[top]!=now)
            {
                bel[sta[top]]=col;
                vi[col]+=yi[sta[top]];
                ci[col]+=hi[sta[top]];
                top--;
            }
            bel[now]=col,vi[col]+=yi[now],ci[col]+=hi[now],top--;
        }
    }
    void dfs(int now,int lit)
    {
        if(lit<=0) return;
        int v;
        for(int i=head[now];i;i=E[i])
            if(lit>=vi[V[i]])
            {
                v=V[i];
                for(int e=0;e<=lit;e++)
                    dp[v][e]=dp[now][e];
                dfs(v,lit-vi[v]);
                for(int e=lit;e>=vi[v];e--)
                    dp[now][e]=max(dp[now][e],dp[v][e-vi[v]]+ci[v]);
            }
    }
    int main()
    {
        in(n),in(m);
        for(int i=1;i<=n;i++) in(yi[i]);
        for(int i=1;i<=n;i++) in(hi[i]);
        int u,v;
        for(int i=1;i<=n;i++)
        {
            in(u),v=i;
            if(u!=0)
            {
                E[++cnt]=head[u],V[cnt]=v,head[u]=cnt;
            }
            Edge[i].u=u,Edge[i].v=v;
        }
        for(int i=1;i<=n;i++)
            if(!dfn[i])
                tarjan(i);
        num=n,cnt=0;
        memset(head,0,sizeof(head));
        for(int i=1;i<=num;i++)
            if(bel[Edge[i].u]!=bel[Edge[i].v])
            {
                if(Edge[i].u!=0)
                {
                    E[++cnt]=head[bel[Edge[i].u]];
                    V[cnt]=bel[Edge[i].v];
                    head[bel[Edge[i].u]]=cnt;
                    vis[bel[Edge[i].v]]=true;
                }
                else
                {
                    E[++cnt]=head[n+1];
                    V[cnt]=bel[Edge[i].v];
                    vis[bel[Edge[i].v]]=true;
                    head[n+1]=cnt;
                }
            }
        for(int i=1;i<=col;i++)
            if(!vis[i])
            {
                E[++cnt]=head[n+1];
                V[cnt]=i;
                head[n+1]=cnt;
            }
        dfs(n+1,m);
        cout<<dp[n+1][m];
        fclose(stdin),fclose(stdout);
        return 0;
    }
    View Code

    T2 codevs 3305 水果姐逛水果街Ⅱ

    http://codevs.cn/problem/3305/

    树链剖分维护前面减后面的最大值,后面减前面的最大值

    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #include<cstdio>
    #define lson k<<1
    #define rson k<<1|1
    using namespace std;
    const int N=200010;
    int front[N],to[N<<1],nxt[N<<1],tot,dfn[N],id[N],a[N];
    int ls[N<<2],rs[N<<2],mi[N<<2],mx[N<<2];
    int n,siz[N],dep[N],bl[N],fa[N];
    struct  node
    {
        int x,y,z;
    };
    inline void read(int &x)
    {
        x=0; char c=getchar();
        while(!isdigit(c)) c=getchar();
        while(isdigit(c)) { x=x*10+c-'0' ; c=getchar(); }
    }
    void add(int u,int v)
    {
        to[++tot]=v; nxt[tot]=front[u]; front[u]=tot;
        to[++tot]=u; nxt[tot]=front[v]; front[v]=tot;
    }
    void dfs1(int x,int f)
    {
        siz[x]=1;
        for(int i=front[x];i;i=nxt[i])
            if(to[i]!=f)
            {
                dep[to[i]]=dep[x]+1;
                fa[to[i]]=x;
                dfs1(to[i],x);
                siz[x]+=siz[to[i]]; 
            }
    }
    void dfs2(int x,int top)
    {
        bl[x]=top;
        dfn[x]=++tot;
        id[tot]=x;
        int y=0;
        for(int i=front[x];i;i=nxt[i])
            if(to[i]!=fa[x] && siz[to[i]]>siz[y]) y=to[i];
        if(!y) return;
        dfs2(y,top);
        for(int i=front[x];i;i=nxt[i])
            if(to[i]!=fa[x] && to[i]!=y) dfs2(to[i],to[i]);     
    }
    inline void up(int k)
    {
        mi[k]=min(mi[lson],mi[rson]);
        mx[k]=max(mx[lson],mx[rson]);
        ls[k]=max(mx[rson]-mi[lson],max(ls[lson],ls[rson]));
        rs[k]=max(mx[lson]-mi[rson],max(rs[lson],rs[rson])); 
    }
    void build(int k,int l,int r)
    {
        if(l==r)
        {
            mi[k]=mx[k]=a[id[l]];
            return;
        }
        int mid=l+r>>1;
        build(lson,l,mid);
        build(rson,mid+1,r);
        up(k);
    }
    int getlca(int u,int v)
    {
        while(bl[u]!=bl[v])
        {
            if(dep[bl[u]]<dep[bl[v]]) swap(u,v);
            u=fa[bl[u]];
        }
        return dep[u]>dep[v] ? v : u;
    }
    node qleft(int k,int l,int r,int opl,int opr)
    {
        if(l>=opl && r<=opr) return (node){mi[k],mx[k],ls[k]}; 
        int mid=l+r>>1;
        if(opr<=mid) return qleft(lson,l,mid,opl,opr);
        if(opl>mid) return qleft(rson,mid+1,r,opl,opr);
        node lch=qleft(lson,l,mid,opl,opr),rch=qleft(rson,mid+1,r,opl,opr);
        return (node){min(lch.x,rch.x),max(lch.y,rch.y),max(rch.y-lch.x,max(lch.z,rch.z))}; 
    }
    node fleft(int x,int y)
    {
        if(bl[x]==bl[y]) return qleft(1,1,n,dfn[y],dfn[x]);
        node lch,rch=qleft(1,1,n,dfn[bl[x]],dfn[x]);
        x=fa[bl[x]];
        //if(id[bl[x]]<id[bl[y]]) swap(x,y);
        while(bl[x]!=bl[y])
        {
            lch=qleft(1,1,n,dfn[bl[x]],dfn[x]);
            rch.z=max(rch.y-lch.x,max(lch.z,rch.z));
            rch.x=min(lch.x,rch.x),rch.y=max(lch.y,rch.y);
            x=fa[bl[x]];
        }
        lch=qleft(1,1,n,dfn[y],dfn[x]);
        rch.z=max(rch.y-lch.x,max(lch.z,rch.z));
        rch.x=min(lch.x,rch.x),rch.y=max(lch.y,rch.y);
        return rch;
    }
    node qright(int k,int l,int r,int opl,int opr)
    {
        if(l>=opl && r<=opr) return (node){mi[k],mx[k],rs[k]};
        int mid=l+r>>1;
        if(opr<=mid) return qright(lson,l,mid,opl,opr);
        if(opl>mid) return qright(rson,mid+1,r,opl,opr);
        node lch=qright(lson,l,mid,opl,opr),rch=qright(rson,mid+1,r,opl,opr);
        return (node){ min(lch.x,rch.x),max(lch.y,rch.y),max(lch.y-rch.x,max(lch.z,rch.z))};
    }
    node fright(int x,int y)
    {
        if(bl[x]==bl[y]) return qright(1,1,n,dfn[y],dfn[x]);
        node rch=qright(1,1,n,dfn[bl[x]],dfn[x]),lch;
        x=fa[bl[x]];
    //    if(id[bl[x]]<id[bl[y]]) swap(x,y);
        while(bl[x]!=bl[y])
        {
            lch=qright(1,1,n,dfn[bl[x]],dfn[x]);
            rch.z=max(lch.y-rch.x,max(lch.z,rch.z));
            rch.x=min(lch.x,rch.x),rch.y=max(lch.y,rch.y);
            x=fa[bl[x]];
        }
        lch=qright(1,1,n,dfn[y],dfn[x]);
        rch.z=max(lch.y-rch.x,max(lch.z,rch.z));
        rch.x=min(lch.x,rch.x),rch.y=max(lch.y,rch.y);
        return rch;
    }
    int main()
    {
        memset(mi,127/3,sizeof(mi));
        int m,u,v,lca;
        read(n);
        for(int i=1;i<=n;i++) read(a[i]);
        for(int i=1;i<n;i++) read(u),read(v),add(u,v);
        dfs1(1,0);
        tot=0;
        dfs2(1,1);
        build(1,1,n);
        read(m);
        while(m--)
        {
            read(u),read(v);
            lca=getlca(u,v);
            if(u==lca) printf("%d
    ",fleft(v,lca).z);
            else if(v==lca) printf("%d
    ",fright(u,lca).z);
            else
            {
                node lch=fleft(v,lca),rch=fright(u,lca);
                printf("%d
    ",max(lch.y-rch.x,max(lch.z,rch.z)));
            }
        }
        return 0;
    }
    View Code

    T3 hdu 1798 50 years, 50 colors

    http://acm.hdu.edu.cn/showproblem.php?pid=1498

    枚举颜色

    如果(x,y)有气球,则由x向y连边

    然后二分图最小点覆盖=最大匹配数

    #include<cstdio>
    #include<cstring>
    using namespace std;
    int a[101][101];
    bool v[101],vv[51];
    int match[10011];
    int tot,front[101],to[20001],nxt[20001];
    int ans[51];
    void add(int u,int v)
    {
        to[++tot]=v; nxt[tot]=front[u]; front[u]=tot;
    }
    bool dfs(int u)
    {
        for(int i=front[u];i;i=nxt[i])
            if(!v[to[i]])
            {
                v[to[i]]=true;
                if(!match[to[i]] || dfs(match[to[i]]))
                {
                    match[to[i]]=u;
                    return true;
                }
            }
        return false;
    }
    int main()
    {
        //freopen("T3.in","r",stdin);
        //freopen("T3.out","w",stdout);
        int n,k,res;
        bool ok;
        while(scanf("%d%d",&n,&k))
        {
            if(!n) return 0;
            memset(vv,false,sizeof(vv));
            ok=false;
            for(int i=1;i<=n;i++)
                for(int j=1;j<=n;j++)
                    scanf("%d",&a[i][j]),vv[a[i][j]]=true;
            ans[0]=0;
            for(int i=1;i<=50;i++)
                if(vv[i])
                {    
                    tot=0;
                    memset(front,0,sizeof(*front)*(n+1));
                    res=0;
                    for(int j=1;j<=n;j++)
                        for(int k=1;k<=n;k++)
                            if(a[j][k]==i) add(j,k);
                    memset(match,0,sizeof(*match)*(n+1));
                    for(int j=1;j<=n;j++)
                    {
                        memset(v,false,sizeof(*v)*(n+1));
                        if(dfs(j)) res++;
                    }
                    if(res>k) ans[++ans[0]]=i;
                }
            if(!ans[0]) printf("-1");
            else 
            {
                for(int i=1;i<ans[0];i++) printf("%d ",ans[i]);
                printf("%d",ans[ans[0]]);
            }
            printf("
    ");
        }        
    }
    View Code
  • 相关阅读:
    cron表达式解释
    mysql explain执行计划
    基于Groovy编写Ngrinder脚本常用方法
    JVM内存结构、参数调优和内存泄露分析
    Jmeter教程 简单的压力测试
    jmeter接口测试之登录测试
    jmeter之线程组的使用
    使用ANT自动执行JMeter用例
    Jmeter参数化随机取值实现
    Jmeter测试接口文档
  • 原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/7561977.html
Copyright © 2020-2023  润新知