CF868F Yet Another Minimization Problem

题目描述

You are given an array of nn integers a_{1}...\ a_{n}a1... an . The cost of a subsegment is the number of unordered pairs of distinct indices within the subsegment that contain equal elements. Split the given array into kk non-intersecting non-empty subsegments so that the sum of their costs is minimum possible. Each element should be present in exactly one subsegment.

输入格式

The first line contains two integers nn and kk ( 2<=n<=10^{5}2<=n<=105 , 2<=k<=min\ (n,20))2<=k<=min (n,20)) — the length of the array and the number of segments you need to split the array into.

The next line contains nn integers a_{1},a_{2},...,a_{n}a1,a2,...,an ( 1<=a_{i}<=n1<=ai<=n ) — the elements of the array.

输出格式

Print single integer: the minimum possible total cost of resulting subsegments.

题意翻译

题目描述:给定一个序列 aa,要把它分成 kk 个子段。每个子段的费用是其中相同元素的对数。求所有子段的费用之和的最小值。

输入格式:第一行输入 nn(序列长度)和 kk(需分子段数)。接下来一行有 nn 个数,第 ii 个数表示序列的第 ii 个元素 a_iai

输出格式:输出一个数,费用和的最小值。

2 \leq n \leq 10^52n105,2 \leq k \leq min(n,20)2kmin(n,20),1 \leq a_i \leq n1ain 。

输入输出样例

输入 #1
7 3
1 1 3 3 3 2 1
输出 #1
1
输入 #2
10 2
1 2 1 2 1 2 1 2 1 2
输出 #2
8
输入 #3
13 3
1 2 2 2 1 2 1 1 1 2 2 1 1
输出 #3
9

说明/提示

In the first example it's optimal to split the sequence into the following three subsegments: [1][1] , [1,3][1,3] , [3,3,2,1][3,3,2,1] . The costs are 00 , 00 and 11 , thus the answer is 11 .

In the second example it's optimal to split the sequence in two equal halves. The cost for each half is 44 .

In the third example it's optimal to split the sequence in the following way: [1,2,2,2,1][1,2,2,2,1] , [2,1,1,1,2][2,1,1,1,2] , [2,1,1][2,1,1] . The costs are 44 , 44 , 11 .

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 using namespace std;
 6 int c[100005],tr,tl,f[30][100005],a[100005],s,n,k;
 7 int get(int l,int r)
 8 {
 9     while (tl<l) 
10     {
11         c[a[tl]]--;
12         s-=c[a[tl]];
13         tl++;
14     }
15     while (tl>l)
16     {
17         tl--;
18         s+=c[a[tl]];
19         c[a[tl]]++;
20     }
21     while (tr<r)
22     {
23         tr++;
24         s+=c[a[tr]];
25         c[a[tr]]++;
26     }
27     while (tr>r)
28     {    
29         c[a[tr]]--;
30         s-=c[a[tr]];
31         tr--;
32     } 
33     return s;
34 }
35 void solve(int x,int l,int r,int L,int R)
36 {int i,Mid;
37     if (l>r) return;
38     int mid=(l+r)/2;
39     Mid=mid;
40     for (i=L;i<=min(mid-1,R);i++)
41     {
42         int t=f[x-1][i]+get(i+1,mid);
43         if (f[x][mid]>=t) 
44         {
45             f[x][mid]=t;
46             Mid=i;
47         }
48     }
49     solve(x,l,mid-1,L,Mid);
50     solve(x,mid+1,r,Mid,R);
51 }
52 int main()
53 {int i,j;
54     scanf("%d%d",&n,&k);
55     for (i=1;i<=n;i++)
56     scanf("%d",&a[i]);
57     memset(f,127/2,sizeof(f));
58     tl=1;tr=0;
59     for (i=1;i<=n;i++)
60     {
61         f[1][i]=get(1,i);
62     } 
63     for (i=2;i<=k;i++)
64     {
65         solve(i,i,n,i-1,n);
66     }
67     printf("%d",f[k][n]);
68 }

 

posted @ 2020-02-01 15:39  Z-Y-Y-S  阅读(247)  评论(0编辑  收藏  举报