zoukankan      html  css  js  c++  java
  • UOJ#110. 【APIO2015】Bali Sculptures 贪心 动态规划

    原文链接https://www.cnblogs.com/zhouzhendong/p/UOJ110.html

    题解

    我们发现n=2000 的子任务保证A=1!

    分两种情况讨论:

    $nleq 100$:

      贪心地从高位到低位逐位考虑,看当前位是否可以放 0。用 $dp[i][j]$ 表示前 $i$ 个数是否可以在各段sum的or值不超过当前上限的情况下分成 $j$ 段。

      时间复杂度 $O(n^3 log V)$ 。

    $A = 1$:

      贪心地从高位到低位逐位考虑,看当前位置是否可以放0。 用 $dp[i][0/1]$ 表示前 $i$ 个数,在各段sum的or值不超过当前上限的情况下,当前位的or值是 $0/1$ 的情况下最少分成几段。

      时间复杂度 $O(n^2 log V)$ 。

    代码

    #include <bits/stdc++.h>
    #define clr(x) memset(x,0,sizeof (x))
    using namespace std;
    typedef long long LL;
    LL read(){
    	LL x=0,f=0;
    	char ch=getchar();
    	while (!isdigit(ch))
    		f|=ch=='-',ch=getchar();
    	while (isdigit(ch))
    		x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
    	return f?-x:x;
    }
    const int N=2005;
    int n,A,B;
    LL a[N];
    void ckMin(int &x,int y){
    	x=x<y?x:y;
    }
    namespace so1{
    	const int N=105;
    	int dp[N][N];
    	int check(LL v){
    		clr(dp);
    		dp[0][0]=1;
    		for (int i=1;i<=n;i++)
    			for (int j=0;j<i;j++)
    				if ((v|(a[i]-a[j]))==v)
    					for (int k=0;k<n;k++)
    						dp[i][k+1]|=dp[j][k];
    		for (int i=1;i<=n;i++)
    			if (A<=i&&i<=B&&dp[n][i])
    				return 1;
    		return 0;
    	}
    	void main(){
    		LL ans=0;
    		for (int i=40;i>=0;i--)
    			if (!check(ans|((1LL<<i)-1)))
    				ans|=1LL<<i;
    		cout<<ans<<endl;
    	}
    }
    namespace so2{
    	const int N=2005;
    	int dp[N][2];
    	void main(){
    		LL ans=0;
    		for (int d=40;d>=0;d--){
    			for (int i=0;i<N;i++)
    				dp[i][0]=dp[i][1]=1e9;
    			dp[0][0]=0;
    			LL v=ans|((1LL<<(d+1))-1);
    			for (int i=1;i<=n;i++)
    				for (int j=0;j<i;j++)
    					if ((v|(a[i]-a[j]))==v)
    						for (int t=0;t<2;t++)
    							ckMin(dp[i][t|((a[i]-a[j])>>d&1LL)],dp[j][t]+1);
    			if (dp[n][0]>B)
    				ans|=1LL<<d;
    		}
    		cout<<ans<<endl;
    	}
    }
    int main(){
    	n=read(),A=read(),B=read();
    	for (int i=1;i<=n;i++)
    		a[i]=a[i-1]+read();
    	if (n<=100)
    		so1::main();
    	else
    		so2::main();
    	return 0;
    }
    

      

  • 相关阅读:
    比较器
    堆排序
    快速排序
    荷兰国旗问题
    python查漏补缺 --- 基础概念及控制结构
    redis 交集、并集、差集
    spark问题
    IDEA写scala简单操作
    hive 中遇到的正则
    scala模式匹配
  • 原文地址:https://www.cnblogs.com/zhouzhendong/p/UOJ110.html
Copyright © 2011-2022 走看看