BZOJ 1786: [Ahoi2008]Pair 配對 題解

【原題】

1786: [Ahoi2008]Pair 配對

Time Limit: 10 Sec  Memory Limit: 64 MB
Submit: 399  Solved: 241
[Submit][Status]

Description

Input

Output

Sample Input

5 4
4 2 -1 -1 3

Sample Output

4

HINT

Source


【分析】一看到就感覺有思路,好像-1的格子有什麼規律。於是開始YY。

簡單的腦補:設A,B,C三個點,A,C是-1。顯然,A、C的大小關係和A左邊、B右邊的無關。

若A<=C。如果B>C逆序對就是1 ,否則是0。

若A>C。如果B>C逆序對就是2 ,否則是1。

顯然-1的格子是單調上升的最好。

然後的DP真的是太水了。先求出原來數的逆序對個數,然後只考慮-1的點造成的逆序對增量。

設f[i][j]是到第i個-1的點,改成數字j的最少逆序增量。顯然f[i][j]=min(f[i-1][k]+cost)。而代價是1--i中比j大的數和i+1--n中比j小的數的和。可以先預處理出來。

還有,根據這個方程,除了狀壓外,還可以把時間效率從NK^2壓成NK。

【造數據程序】無限WA!於是就找了個標程對拍。

#include<cstdio>
#include<cstdlib>
#include<ctime>
using namespace std;
int main()
{
  freopen("1786.in","w",stdout);
  srand((int)time(0));
  int n=1000,k=100;
  printf("%d %d\n",n,k);
  for (int i=1;i<=n;i++)
  {
    int num=rand()%10;
    if (!num) printf("-1 ");else printf("%d ",rand()%10+1);
  }
  return 0;
}

好不容易發現錯誤:最後更新Min的時候我用f數組。看上去因爲f和g是一樣的(memcpy),但其實如果-1只有1個,就不會有f了,而邊界條件是g。於是應該改用g來更新Min。

【代碼】

#include<cstdio>
#include<algorithm>
#include<cstring>
#define N 10005
#define K 105
using namespace std;
int place[N],big[N][K],small[N][K],f[K],g[K],a[N];
int n,L,i,j,m,now,last,ans,Min;
int main()
{
  freopen("1786.in","r",stdin);
  freopen("1786.out","w",stdout);
  scanf("%d%d",&n,&L);
  for (i=1;i<=n;i++) {scanf("%d",&a[i]);if (a[i]==-1) place[++m]=i;}
  for (i=2;i<=n;i++)
  {
    memcpy(big[i],big[i-1],sizeof(big[i-1]));
    if (a[i-1]>-1) for (j=1;j<a[i-1];j++) big[i][j]++;
  }
  for (i=n-1;i;i--)
  {
    memcpy(small[i],small[i+1],sizeof(small[i+1]));
    if (a[i+1]>-1) for (j=L;j>a[i+1];j--) small[i][j]++;
  }
  for (i=1;i<=n;i++) if (a[i]>-1) ans+=small[i][a[i]];
  for (i=1;i<=L;i++) g[i]=big[place[1]][i]+small[place[1]][i];
  for (i=2;i<=m;i++)
  {
    for (last=2;last<=L;last++)
      g[last]=min(g[last],g[last-1]);
    for (now=1;now<=L;now++)
      f[now]=g[now]+big[place[i]][now]+small[place[i]][now];
    memcpy(g,f,sizeof(f));
  }
  Min=g[1];for (i=2;i<=L;i++) Min=min(Min,g[i]);
  printf("%d",ans+Min);
  return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章