[CmdOI2019]任务分配问题

题目描述

在某台有kk个CPU的计算机中,有nn个计算任务等待执行。

a_iai​为第ii个任务的优先级,方便起见,aa为一个排列。

现在,要将这些任务分配给CPU去解决。

由于内存等原因,一个CPU只能负责连续一段的任务,并且要按(从左到右的)顺序执行。

在某个CPU内,无序度定义为 : 前者先执行,而后者优先级高的任务对的个数。

请最小化每个CPU的无序度之和。

输入格式

第一行两个整数n,kn,k,分别表示任务个数和CPU个数。

第二行nn个整数,表示a_{1...n}a1...n​

输出格式

输出一个整数,表示最小的无序度之和。

输入输出样例

输入 #1复制
5 1
1 5 4 2 3
输出 #1复制
5
输入 #2复制
5 2
1 5 4 2 3
输出 #2复制
1
输入 #3复制
8 3
1 3 5 2 7 4 8 6
输出 #3复制
4
说明/提示

测试点编号 n k
1~2 25000 1
3 25000 2
4~5 1000 10
6~10 25000 25
(保证k\leq nk≤n , #6~10时限2S)

样例解释:

样例1
此时只能把所有任务交给单独的一个CPU。

第一个任务和其他所有任务都形成无序任务对。

此外最后两个任务也形成无序任务对,共5个。

样例2
第一个CPU单独处理任务1,无序度为0;

第二个CPU处理\{5,4,2,3\}{5,4,2,3}无序度为1;

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 using namespace std;
 6 int c[50005],tr,tl,f[30][25005],a[25005],s,n,k;
 7 void del(int x)
 8 {
 9     while (x<=n)
10     {
11         c[x]-=1;
12         x+=(x&(-x));
13     }
14 }
15 void add(int x)
16 {
17     while (x<=n)
18     {
19         c[x]+=1;
20         x+=(x&(-x));
21     }
22 }
23 int query(int x)
24 {
25     int sum=0;
26     while (x)
27     {
28         sum+=c[x];
29         x-=(x&(-x));
30     }
31     return sum;
32 }
33 int get(int l,int r)
34 {
35     while (tl<l) 
36     {
37         del(a[tl]);
38         s-=tr-tl-query(a[tl]);
39         tl++;
40     }
41     while (tl>l)
42     {
43         tl--;
44         s+=tr-tl-query(a[tl]);
45         add(a[tl]);
46     }
47     while (tr<r)
48     {
49         tr++;
50         s+=query(a[tr]);
51         add(a[tr]);
52     }
53     while (tr>r)
54     {    
55         del(a[tr]);
56         s-=query(a[tr]);
57         tr--;
58     } 
59     return s;
60 }
61 void solve(int x,int l,int r,int L,int R)
62 {int i,Mid;
63     if (l>r) return;
64     int mid=(l+r)/2;
65     Mid=mid;
66     for (i=L;i<=min(mid-1,R);i++)
67     {
68         int t=f[x-1][i]+get(i+1,mid);
69         if (f[x][mid]>=t) 
70         {
71             f[x][mid]=t;
72             Mid=i;
73         }
74     }
75     solve(x,l,mid-1,L,Mid);
76     solve(x,mid+1,r,Mid,R);
77 }
78 int main()
79 {int i,j;
80     scanf("%d%d",&n,&k);
81     for (i=1;i<=n;i++)
82     scanf("%d",&a[i]);
83     memset(f,127/2,sizeof(f));
84     tl=1;tr=0;
85     for (i=1;i<=n;i++)
86     {
87         f[1][i]=get(1,i);
88     } 
89     for (i=2;i<=k;i++)
90     {
91         solve(i,i,n,i-1,n);
92     }
93     printf("%d",f[k][n]);
94 }

 

posted @ 2020-01-31 17:26  Z-Y-Y-S  阅读(273)  评论(0编辑  收藏  举报