询问长度超过log(m)则一定能把所有数都选到,然后就可以n*m*log(m)处理了
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
typedef long long ll;
vector<int>v[1000010];
ll dp[1000010][22],sum;
ll m1[(1<<20)+10],m2[(1<<20)+10];
int main()
{
int n,m,q;
scanf("%d%d%d",&n,&m,&q);
for(int i=1;i<=n;i++){
for(int j=0;j<=m;j++)v[i].push_back(0);
}
for(int i=1;i<=n;i++){
int x,y;scanf("%d",&x);
while(x--){
scanf("%d",&y);v[i][y]=1;
}
}
for(int i=1;i<=m;i++)sum+=1ll*i*i;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++)m1[j]=0;
for(int j=i;j<=n&&j-i+1<=20;j++){
if(dp[i][j-i]==sum)dp[i][j-i+1]=sum;
else {
for(int k=1;k<=m;k++){
if(v[j][k]==0)m1[k]|=(1<<(j-i));
}
for(int k=0;k<(1<<(j-i+1));k++)m2[k]=0;
for(int k=1;k<=m;k++){m2[m1[k]]+=1ll*k*k;}
ll mi=sum;
for(int k=0;k<(1<<(j-i+1));k++)mi=min(mi,m2[k]);
dp[i][j-i+1]=sum-mi;
}
}
}
while(q--){
int l,r;
scanf("%d%d",&l,&r);
if(r-l+1<=20)printf("%lld\n",dp[l][r-l+1]);
else printf("%lld\n",sum);
}
return 0;
}
本文解析了一个算法竞赛题目,讨论了如何通过动态规划解决特定类型的组合问题,并提供了一段C++代码实现,该方法适用于处理涉及大量数据的选择问题。
648

被折叠的 条评论
为什么被折叠?



