ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

高维前缀和(sosdp) & AT4168 [ARC100C] Or Plus Max

2021-07-20 18:04:38  阅读:201  来源: 互联网

标签:前缀 int Max AT4168 sosdp 二维 maxn 子集 include


洛谷传送门


高维前缀和

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

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;
}

标签:前缀,int,Max,AT4168,sosdp,二维,maxn,子集,include
来源: https://www.cnblogs.com/yinyuqin/p/15036070.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有