• Luogu P1864 [NOI2009]二叉查找树


    题目
    (v)表示权值,(F)表示频率。
    首先我们显然可以把这个权值离散化。
    然后我们想一下,这个东西它是一棵树对吧,但是我们改变权值会引起其树形态的改变,这样很不好做,所以我们考虑把它转化为序列上的问题。
    我们知道这是一个treap对吧,所以它的中序遍历的数据值是递增的,我们考虑这个性质入手,把所有点按数据值从小到大排序,那么连续一段点在树上显然是一个连通块。
    (f_{i,j,o})表示只考虑([i,j])的点,在所有权值(ge o)的情况下的最小答案。那么我们就可以枚举权值和区间,再枚举这个区间的点构成的树的根进行转移了。
    设枚举的根为(k),那么我们需要满足区间内其它点的权值都比它大。
    转移分为两种:
    (1.(v_kge o):f_{i,j,o}=min(f_{i,j,o},f_{i,k-1,v_k}+f_{k+1,j,v_k}+sumlimits_{p=i}^j F_p))
    (2.f_{i,j,o}=min(f_{i,j,o},f_{i,k-1,o}+f_{k+1,j,o}+sumlimits_{p=i}^j F_p+K))

    #include<bits/stdc++.h>
    using namespace std;
    const int N=73;
    struct node{int x,v,f;}a[N];
    int operator<(node a,node b){return a.x<b.x;}
    int f[N][N][N],t[N];
    int read(){int x;cin>>x;return x;}
    void min(int &a,int b){a=a<b? a:b;}
    int main()
    {
        int i,j,k,o,n=read(),K=read();memset(f,63,sizeof f);
        for(i=1;i<=n;++i) a[i].x=read();
        for(i=1;i<=n;++i) t[i]=a[i].v=read();
        for(i=1;i<=n;++i) a[i].f=read();
        sort(a+1,a+n+1),sort(t+1,t+n+1);
        for(i=1;i<=n;++i) a[i].v=lower_bound(t,t+n+1,a[i].v)-t;
        for(i=2;i<=n;++i) a[i].f+=a[i-1].f;
        for(i=1;i<=n+1;++i) for(j=0;j<=n;++j) f[i][i-1][j]=0;
        for(o=n;~o;--o)
    	for(i=n;i;--i)
    	    for(j=i;j<=n;++j)
    		for(k=i;k<=j;++k)
    		{
    		    if(a[k].v>=o) min(f[i][j][o],f[i][k-1][a[k].v]+f[k+1][j][a[k].v]+a[j].f-a[i-1].f);
    		    min(f[i][j][o],f[i][k-1][o]+f[k+1][j][o]+K+a[j].f-a[i-1].f);
    		}
        cout<<f[1][n][0];
    }
    
  • 相关阅读:
    Codeforces 985G. Team Players
    关于Hall定理的学习
    bzoj 4561: [JLoi2016]圆的异或并
    UOJ #188. 【UR #13】Sanrd
    LOJ #6053. 简单的函数
    Codeforces F. Cowmpany Cowmpensation
    POJ 3710:Matrix Power Series
    codeforces533E
    luogu2885
    codeforces722E
  • 原文地址:https://www.cnblogs.com/cjoierShiina-Mashiro/p/11728723.html
Copyright © 2020-2023  润新知