zoukankan      html  css  js  c++  java
  • 高维前缀和(sosdp) & AT4168 [ARC100C] Or Plus Max

    洛谷传送门


    高维前缀和

    一维二维前缀和
    首先多维前缀和肯定可以像二维一样进行容斥求出,但是很显然复杂度爆炸。
    所以我们使用另一种求法。
    二维前缀和:

    for(int i=1;i<=n;i++){
    	for(int j=1;j<=m;j++){
    		a[i][j]+=a[i-1][j];
    	}
    }
    for(int i=1;i<=n;i++){
    	for(int j=1;j<=m;j++){
    		a[i][j]+=a[i][j-1];
    	}
    }
    

    可以理解为先对于每一列求关于行的前缀和,再在每一行加起来。
    三维前缀和:

    for(int i=1;i<=a;i++){
    	for(int j=1;j<=b;j++){
    		for(int k=1;k<=c;k++){
    			a[i][j][k]+=a[i-1][j][k]; 
    		}
    	}
    }
    for(int i=1;i<=a;i++){
    	for(int j=1;j<=b;j++){
    		for(int k=1;k<=c;k++){
    			a[i][j][k]+=a[i][j-1][k]; 
    		}
    	}
    }
    for(int i=1;i<=a;i++){
    	for(int j=1;j<=b;j++){
    		for(int k=1;k<=c;k++){
    			a[i][j][k]+=a[i][j][k-1]; 
    		}
    	}
    }
    

    这样n维的前缀和时间复杂度就降到了 (O(na^n))

    应用--子集

    例如

    对于所有的 (i(0≤i≤2n−1)),求解 (sum_{j⊂i}a_j)

    令 dp[i][j] 表示考虑数 j 二进制的后 i 位的子集和。
    于是就有了代码:

    for(int i=1;i<=n;i++){
    	for(int j=0;j<(1<<n);j++){
    		if(j&(1<<(i-1))) dp[i][j]+=dp[i-1][j^(1<<(i-1))];
    		else dp[i][j]=dp[i-1][j];
    	}
    }
    

    但是一般用滚动数组优化一下,于是就有:

    for(int i=0,i<n;i++){
    	for(int j=0;j<(1<<n);j++){
    		if(j&(1<<i)) dp[j]+=dp[j^(1<<i)];
    	}
    }
    

    解题思路

    可以用求子集的方法来解此题。
    用d[i][0/1]表示i的子集中的最大值/次大值。
    注意最后因为题目要求是<=k,所以要取max。

    AC代码

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<ctime>
    using namespace std;
    const int maxn=3e5;
    int nn,n,a[maxn],d[maxn][2],ans;
    void add(int a,int b){
    	if(d[a][0]<d[b][0]){
    		d[a][1]=max(d[a][0],d[b][1]);
    		d[a][0]=d[b][0];
    	}
    	else if(d[a][1]<d[b][0]) d[a][1]=d[b][0];
    }
    int main(){
    	ios::sync_with_stdio(false);
    	cin>>nn;
    	n=1<<nn;
    	for(int i=0;i<n;i++) cin>>d[i][0];
    	for(int i=0;i<nn;i++){
    		for(int j=0;j<n;j++){
    			if(j&(1<<i)) add(j,j^(1<<i));
    		}
    	}
    	for(int i=1;i<n;i++){
    		ans=max(ans,d[i][0]+d[i][1]);
    		cout<<ans<<endl;
    	}
    	return 0;
    }
    
  • 相关阅读:
    推荐一个学习 SharePoint 2010 的站点
    应用反射技术为Infragistics Solution设计例子程序 代码简洁而且学习的效率高
    .NET程序员掌握的.NET技术
    Jpegoptim Tool
    Stack Overflow 漫谈
    NServiceBus最流行的开源企业服务总线AND让创建企业级.NET系统更加容易
    步步为营UML建模系列四、状态图(State)
    Web中的幻灯片组件实现
    轻轻松松SOA: NServiceBus
    细说 ASP.NET Cache 及其高级用法
  • 原文地址:https://www.cnblogs.com/yinyuqin/p/15036070.html
Copyright © 2011-2022 走看看