基准时间限制:1 秒 空间限制:131072 KB
lyk最近计划按顺序做n道题目,每道题目都分为很多分数档次,lyk觉得这些题太简单了,于是它想到了一个好玩的游戏。
lyk决定将每道题目做出其中的某个分数,使得这n道题目的逆序对个数最多。
为了方便,假设共有m个分数档次,并且会给m个分数档次分配一个题目编号,表示该题目会出现这个分数档次。
题目保证每道题都存在至少一个分数档次。(例如样例中5道题目的分数分别是5,6,3,4,7,共有4个逆序对)
Input
第一行两个数n,m(n<=20,m<=100)。 接下来m行,每行一个数ai,表示第ai道题目可能会有i这个分数的档次。
Output
一个数表示最多逆序对个数。
Input示例
5 7 1 2 3 4 1 2 5
Output示例
4
#include <bits/stdc++.h> using namespace std; const int N = 105, M = (1<<20) + 5; int n, m, a[N], all, ff[M], f[2][M], cur; int main() { scanf("%d%d",&n,&m); for(int i=1; i<=m; i++){ int p; scanf("%d",&p); a[i]=p-1; } all = 1<<n; for(int i=0; i<=n; i++) ff[1<<i] = 1; for(int i=1; i<all; i++) ff[i] = ff[i&-i] + ff[i^(i&-i)]; memset(f, -1, sizeof(f)); f[cur][0] = 0; for(int i=0; i<m; i++, cur ^= 1) { int *g = f[cur], *d = f[cur^1]; for(int s=0; s<all; s++) if(g[s] != -1) { d[s] = max(d[s], g[s]); if(~ s & (1<<a[i+1])) { int ns = s | (1<<a[i+1]); d[ns] = max(d[ns], g[s] + ff[ns >> (a[i+1] + 1)]); } g[s] = -1; } } printf("%d\n", f[cur][all-1]); return 0; }
时间: 2024-10-05 21:40:57