传送门
文章目录
- 题意:
- 思路:
题意:
给你nnn个长度为mmm的数组,选出两个来,让他们每一位取maxmaxmax构成新数组bbb,让后最大化bbb的最小值。
思路:
看到m=8m=8m=8,也就是每个数组长度为mmm,很容易想到状压。由于要最大化最小值,我们不妨二分这个最小值,让后将nnn个数组状压成一个二进制,>=mid>=mid>=mid的位置为111,否则为000。这个时候我们只需要找出两个数使其取或后[0,m−1][0,m-1][0,m−1]的每一位都是111即可。
我们发现只需要记录一下当前状态对应的编号,让后28∗282^{8}*2^{8}28∗28枚举状态,让后判断(i∣j)==(1<<m)−1(i|j)==(1<<m)-1(i∣j)==(1<<m)−1即可。
复杂度O(max(nm,22m)∗log(1e9))O(max(nm,2^{2m})*log(1e9))O(max(nm,22m)∗log(1e9))
如果mmm很大怎么办?有没有更好的方法呢?当然是有的。
假设我们知道了状态110101110101110101,那么我们只需要看一下是否存在001010001010001010即可。而这个状态有可能是某个状态的子集,我们不能对于每数都将其子集暴力的加入,这样复杂度会爆掉的,看到大佬有一个好的方法来递推求子集。我们从(1<<m)−1(1<<m)-1(1<<m)−1开始,记为nownownow,让后遍历[0,m−1][0,m-1][0,m−1],记为jjj,看一下now∣(1<<j)now|(1<<j)now∣(1<<j)是否存在,存在的话就说明他是now∣(1<<j)now|(1<<j)now∣(1<<j)的一个子集,就直接继承now∣(1<<j)now|(1<<j)now∣(1<<j)的信息即可。这样递推的复杂度为2m∗m2^m*m2m∗m,显然更加的优秀。
复杂度O(max(nm,2m∗m)∗log(1e9))O(max(nm,2^{m}*m)*log(1e9))O(max(nm,2m∗m)∗log(1e9))
//#pragma GCC optimize(2)
#include<cstdio>
#include<iostream>
#include<string>
#include<cstring>
#include<map>
#include<cmath>
#include<cctype>
#include<vector>
#include<set>
#include<queue>
#include<algorithm>
#include<sstream>
#include<ctime>
#include<cstdlib>
#define X first
#define Y second
#define L (u<<1)
#define R (u<<1|1)
#define pb push_back
#define mk make_pair
#define Mid (tr[u].l+tr[u].r>>1)
#define Len(u) (tr[u].r-tr[u].l+1)
#define random(a,b) ((a)+rand()%((b)-(a)+1))
#define db puts("---")
using namespace std;//void rd_cre() { freopen("d://dp//data.txt","w",stdout); srand(time(NULL)); }
//void rd_ac() { freopen("d://dp//data.txt","r",stdin); freopen("d://dp//AC.txt","w",stdout); }
//void rd_wa() { freopen("d://dp//data.txt","r",stdin); freopen("d://dp//WA.txt","w",stdout); }typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int,int> PII;const int N=1000010,mod=1e9+7,INF=0x3f3f3f3f;
const double eps=1e-6;int n,m;
int a[N][10];
int id[1010],ans1,ans2;
bool flag;bool check(int mid)
{memset(id,0,sizeof(id));for(int i=0;i<n;i++){int now=0;for(int j=0;j<m;j++)if(a[i][j]>=mid) now+=(1<<j);id[now]=i+1;}int tot=(1<<m);for(int i=tot-1;i>=0;i--)for(int j=0;j<m;j++)if(id[i|(1<<j)])id[i]=id[i|(1<<j)];for(int i=tot-1;i>=0;i--)if(id[i]&&id[i^(tot-1)]){ans1=id[i];ans2=id[i^(tot-1)];return true;}return false;
}int main()
{
// ios::sync_with_stdio(false);
// cin.tie(0);scanf("%d%d",&n,&m);for(int i=0;i<n;i++) for(int j=0;j<m;j++) scanf("%d",&a[i][j]);int l=0,r=1e9,ans;while(l<=r){int mid=l+r>>1;if(check(mid)) l=mid+1;else r=mid-1;}printf("%d %d\n",ans1,ans2);return 0;
}
/**/
复杂度O(max(nm,22m)∗log(1e9))O(max(nm,2^{2m})*log(1e9))O(max(nm,22m)∗log(1e9))
//#pragma GCC optimize(2)
#include<cstdio>
#include<iostream>
#include<string>
#include<cstring>
#include<map>
#include<cmath>
#include<cctype>
#include<vector>
#include<set>
#include<queue>
#include<algorithm>
#include<sstream>
#include<ctime>
#include<cstdlib>
#define X first
#define Y second
#define L (u<<1)
#define R (u<<1|1)
#define pb push_back
#define mk make_pair
#define Mid (tr[u].l+tr[u].r>>1)
#define Len(u) (tr[u].r-tr[u].l+1)
#define random(a,b) ((a)+rand()%((b)-(a)+1))
#define db puts("---")
using namespace std;//void rd_cre() { freopen("d://dp//data.txt","w",stdout); srand(time(NULL)); }
//void rd_ac() { freopen("d://dp//data.txt","r",stdin); freopen("d://dp//AC.txt","w",stdout); }
//void rd_wa() { freopen("d://dp//data.txt","r",stdin); freopen("d://dp//WA.txt","w",stdout); }typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int,int> PII;const int N=1000010,mod=1e9+7,INF=0x3f3f3f3f;
const double eps=1e-6;int n,m;
int a[N][10];
int id[1010],ans1,ans2;
bool flag;bool check(int mid)
{memset(id,0,sizeof(id));for(int i=0;i<n;i++){int now=0;for(int j=0;j<m;j++)if(a[i][j]>=mid) now+=(1<<j);id[now]=i+1;}for(int i=0;i<(1<<m);i++)for(int j=0;j<(1<<m);j++)if(id[i]&&id[j]&&(i|j)==((1<<m)-1)){ans1=id[i],ans2=id[j];return true;}return false;
}int main()
{
// ios::sync_with_stdio(false);
// cin.tie(0);scanf("%d%d",&n,&m);for(int i=0;i<n;i++) for(int j=0;j<m;j++) scanf("%d",&a[i][j]);int l=0,r=1e9,ans;while(l<=r){int mid=l+r>>1;if(check(mid)) l=mid+1;else r=mid-1;}printf("%d %d\n",ans1,ans2);return 0;
}
/**/