• CF321E Ciel and Gondolas Wqs二分 四边形不等式优化dp 决策单调性


    LINK:CF321E Ciel and Gondolas

    很少遇到这么有意思的题目了。虽然很套路。。

    容易想到dp (f_{i,j})表示前i段分了j段的最小值 转移需要维护一个(cost(i,j))

    暴力显然不太行 不过暴力枚举决策的话 可以预处理前缀和线性推出。

    显然想要优化决策的话第一步就需要O(1)求出(cost(i,j))

    经过画图 可以发现预处理出(g[i][j])表示从((1,1))((i,j))这个矩形中的点值和 和 (sum_i)表示((1,1))((i,i))的点值和 就可以O(1)求值了。

    观察dp转移式发现这是典型的四边形不等式优化dp 套用决策单调性 复杂度(ncdot kcdot logn)

    强制k段 显然可以Wqs二分来解除限制 不过这样不太能分治做了 需要采用单调队列来做。

    但存在一个问题 可能有mid的时候为k-1 mid+1的时候为k+1.

    关于这个问题 通过值相等的时候分段多的方法来使上面情况合法化 最终尽管可能>=k的但是仍然可以构造出等于k的情况。

    如果是小数二分的话显然不必要 因为可以精确到固定的点。

    所以总复杂度(ncdot logMx cdot logn)

    code
    //#include<bitsstdc++.h>
    #include<iostream>
    #include<iomanip>
    #include<cstdio>
    #include<cstring>
    #include<string>
    #include<ctime>
    #include<cmath>
    #include<cctype>
    #include<cstdlib>
    #include<queue>
    #include<deque>
    #include<stack>
    #include<vector>
    #include<algorithm>
    #include<utility>
    #include<bitset>
    #include<set>
    #include<map>
    #define ll long long
    #define db double
    #define INF 10000000000000010ll
    #define ldb long double
    #define pb push_back
    #define put_(x) printf("%d ",x);
    #define get(x) x=read()
    #define gt(x) scanf("%d",&x)
    #define gi(x) scanf("%lf",&x)
    #define put(x) printf("%d
    ",x)
    #define putl(x) printf("%lld
    ",x)
    #define gc(a) scanf("%s",a+1)
    #define rep(p,n,i) for(RE int i=p;i<=n;++i)
    #define go(x) for(int i=lin[x],tn=ver[i];i;tn=ver[i=nex[i]])
    #define fep(n,p,i) for(RE int i=n;i>=p;--i)
    #define vep(p,n,i) for(RE int i=p;i<n;++i)
    #define pii pair<int,int>
    #define mk make_pair
    #define RE register
    #define P 1000000007
    #define gf(x) scanf("%lf",&x)
    #define pf(x) ((x)*(x))
    #define uint unsigned long long
    #define ui unsigned
    #define EPS 1e-8
    #define sq sqrt
    #define S second
    #define F first
    #define mod 998244353
    using namespace std;
    char buf[1<<15],*fs,*ft;
    inline char getc()
    {
        return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;
    }
    inline int read()
    {
        RE int x=0,f=1;RE char ch=getc();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getc();}
        while(ch>='0'&&ch<='9'){x=((ll)x*10+ch-'0')%mod;ch=getc();}
        return x*f;
    }
    const int MAXN=4010,G=3;
    int n,k,l,r;
    ll f[MAXN];
    int sum[MAXN],pre[MAXN][MAXN];
    int c[MAXN][MAXN],cnt[MAXN];
    struct wy{int l,r,x;}q[MAXN];
    inline int cost(int i,int j)
    {
    	return (sum[j]-c[i-1][j]*2+sum[i-1])>>1;
    }
    inline int pd(int x,int y,int z)
    {
    	if(f[x]+cost(x+1,z)<f[y]+cost(y+1,z))return 0;
    	if(f[x]+cost(x+1,z)==f[y]+cost(y+1,z))return cnt[x]<cnt[y];
    	return 1;
    }
    inline int calc(wy a,int x)
    {
    	int l=a.l,r=a.r+1;
    	while(l<r)
    	{
    		int mid=(l+r)>>1;
    		if(pd(a.x,x,mid))r=mid;
    		else l=mid+1;
    	}
    	return r;
    }
    inline void calc(int x)
    {
    	q[l=r=1]=(wy){1,n,0};
    	rep(1,n,i)
    	{
    		while(l<r&&q[l].r<i)++l;
    		int w=q[l].x;++q[l].l;
    		f[i]=f[w]+cost(w+1,i)+x;cnt[i]=cnt[w]+1;
    		if(pd(q[r].x,i,n))
    		{
    			while(l<=r&&pd(q[r].x,i,q[r].l))--r;
    			if(l>r){q[++r]=(wy){i+1,n,i};continue;}
    			int w=calc(q[r],i);
    			q[r].r=w-1;q[++r]=(wy){w,n,i};
    		}
    	}
    }
    int main()
    {
    	//freopen("1.in","r",stdin);
    	get(n);get(k);
    	rep(1,n,i)
    	{
    		rep(1,n,j)
    		{
    			int get(x);
    			pre[i][j]=pre[i][j-1]+x;
    			c[i][j]=c[i-1][j]+pre[i][j];
    		}
    		sum[i]=sum[i-1]+(pre[i][i]<<1);
    	}
    	int l=0,r=(sum[n]>>1)+1;
    	while(l+1<r)
    	{
    		int mid=(l+r)>>1;
    		calc(mid);
    		if(cnt[n]>=k)l=mid;
    		else r=mid;
    	}
    	calc(r);
    	if(cnt[n]>=k)l=r;else calc(l);
    	putl(f[n]-k*l);return 0;
    }
    
  • 相关阅读:
    里氏代换原则
    依赖倒转原则
    开放-封闭原则
    如何判断对象是否死亡和类是无用的类
    Java内存区域
    Zookeeper使用场景
    zookeeper知识点总结
    前端小技术总结
    lambda表达式的使用
    Comparator进行List集合排序
  • 原文地址:https://www.cnblogs.com/chdy/p/13254790.html
Copyright © 2020-2023  润新知