1. I love max and multiply
题意:
给出两个数组 a a a和 b b b ,定义 c c c数组 c k = m a x ( a i ⋅ b j ) c_k =max(a_i \cdot b_j) ck=max(ai⋅bj) 且 i & j ≥ k i \& j \geq k i&j≥k。求 ∑ i = 0 n − 1 c i \sum\limits_{i=0}^{n-1} c_i i=0∑n−1ci
题解:
先考虑二进制下 k k k为 i & j i\&j i&j 的子集。 设 d p 1 [ i ] [ 1 ] dp1[i][1] dp1[i][1] 表示 i i i 或 i i i 的父亲集合传给 i i i 的最大的 a a a, 设 d p 1 [ i ] [ 0 ] dp1[i][0] dp1[i][0] 表示 i i i 或 i i i 的父亲集合传给 i i i 的最小的 a a a, 设 d p 2 [ i ] [ 1 ] dp2[i][1] dp2[i][1] 表示 i i i 或 i i i 的父亲集合传给 i i i 的最大的 b b b, 设 d p 2 [ i ] [ 0 ] dp2[i][0] dp2[i][0] 表示 i i i 或 i i i 的父亲集合传给 i i i 的最小的 b b b。那么怎么快速将值传递给子集呢。我们可以先求出n-1的位数,然后将每一位都先赋值为1,然后 b f s bfs bfs ,每次都去掉某一位上的1,就可以做到传递给子集。
最后一定要注意的是,我们此时求出来的 c k c_k ck 只满足 k k k 为 i & j i\& j i&j 的子集,并不满足 k ≤ i & j k \leq i\& j k≤i&j ,所以要取个后缀最大值。
代码:
#pragma GCC diagnostic error "-std=c++11"
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
#include<stack>
#include<set>
#include<ctime>
#define iss ios::sync_with_stdio(false)
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
typedef pair<int,int> pii;
const int mod=998244353;
const int MAXN=2e6+5;
const int inf=0x3f3f3f3f;
int vis[MAXN];
ll dp1[MAXN][2];
ll dp2[MAXN][2];
ll ans[MAXN];
queue<int>q;
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
while(!q.empty()) q.pop();
int n;
scanf("%d",&n);
for(int i=0;i<=n-1;i++){
int a;
scanf("%d",&a);
dp1[i][0]=dp1[i][1]=a;
}
for(int i=0;i<=n-1;i++){
int b;
scanf("%d",&b);
dp2[i][0]=dp2[i][1]=b;
}
int temp=n-1;
int cnt=1;
int sum=0;
while(temp)
{
sum+=cnt;
temp/=2;
cnt*=2;
}
q.push(sum);
//cout<<sum<<endl;
for(int i=0;i<=sum;i++)
{
vis[i]=0;
}
vis[sum]=1;
while(!q.empty())
{
int now=q.front();
q.pop();
temp=now;
cnt=1;
while(now)
{
if(now&1)
{
if(temp-cnt<=n-1&&temp<=n-1)
{
dp1[temp-cnt][1]=max(dp1[temp-cnt][1],dp1[temp][1]);
dp1[temp-cnt][0]=min(dp1[temp-cnt][0],dp1[temp][0]);
dp2[temp-cnt][1]=max(dp2[temp-cnt][1],dp2[temp][1]);
dp2[temp-cnt][0]=min(dp2[temp-cnt][0],dp2[temp][0]);
}
if(!vis[temp-cnt])
{
q.push(temp-cnt);
vis[temp-cnt]=1;
}
}
now/=2;
cnt*=2;
}
}
ans[n]=-1e18;
for(int i=n-1;i>=0;i--)
{
ll c1=(dp1[i][1]*dp2[i][1]);
ll c2=(dp1[i][0]*dp2[i][0]);
ll c3=(dp1[i][0]*dp2[i][1]);
ll c4=(dp1[i][1]*dp2[i][0]);
ll maxx=max(c1,c2);
maxx=max(maxx,c3);
maxx=max(maxx,c4);
ans[i]=maxx;
//ans[i]=max(ans[i],ans[i+1]);
}
ll res=0;
for(int i=0;i<n;i++)
{
res=(res+ans[i]%mod+mod)%mod;
}
printf("%lld\n",(res+mod)%mod);
}
}