1150: [CTSC2007] Data backups backup Time Limit:10 Sec Memory limit:162 MB
submit:797 solved:333
[Submit] [Status] Description
Input
The first line entered contains integers n and K, where n (2≤n≤100 000) represents the number of office buildings, and K (1≤K≤N/2) represents the number of network cables available. The next n rows contain only one integer (0≤s≤1000 000 000), representing the distance from each office building to the beginning of the street. These integers will appear sequentially from small to large. Output
The output shall consist of a positive integer, giving the minimum total length of the network cable required to connect the 2K office building to the K pair. Sample Input 5 2
1
3
4
6
Sample Output 4 HINT
The sample above shows the example scenario described above for each test point, if the correct answer is written to the output file, the test point 100% points, or 0 points. 30% of the input data satisfies n≤20. 60% of the input data satisfies N≤10 000.
Greedy + heap.
To read the data difference first, the topic becomes:
Select K nonadjacent numbers from the n-1 number to make them and the smallest.
For "not adjacent" processing is very clever ~
1. First we put all the numbers in the heap
2. Remove the smallest X
3. Next, change this line to his left segment + to the right segment------X, insert the heap
4. Delete the segments on both sides of X
5. Return to 2, repeat K this process
Each time you take a number out of the heap, you are bound to make a total of +1 of the segments taken out and meet the conditions that are not contiguous.
Greedy look, each take out is the smallest, that is to remove the total number of segments more than one of the minimum cost, so the total segment length to meet the smallest.
#include <iostream> #include <algorithm> #include <cstring> #include <cstdlib> #include < cmath> #include <cstdio> #include <queue> #define INF 0x3f3f3f3f #define MP Make_pair #define PA pair<in
T,int> #define M 100000+5 using namespace std;
int n,m,len[m],pre[m],ne[m];
priority_queue<pa,vector<pa>,greater<pa> > Q;
void read (int &tmp) {tmp=0;
Char Ch=getchar ();
int fu=1; for (;ch< ' 0 ' | |
Ch> ' 9 '; Ch=getchar ()) if (ch== '-') fu=-1;
for (; ch>= ' 0 ' &&ch<= ' 9 '; Ch=getchar ()) tmp=tmp*10+ch-' 0 ';
Tmp*=fu;
int main () {read (n), read (m);
int x=0,y;
for (int i=1;i<=n;i++) {read (Y);
Len[i]=y-x;
pre[i]=i-1,ne[i]=i+1;
X=y;
int ans=0;
for (int i=2;i<=n;i++) Q.push (MP (Len[i],i));
pre[2]=0,ne[n]=0;
for (int i=1;i<=m;i++) {while (Q.top (). First!=len[q.top (). Second]) Q.pop ();
int X=q.top (). Second,l=pre[x],r=ne[x];
ANS+=LEN[X];
Q.pop ();
Pre[ne[x]=ne[r]]=x; Ne[pre[X]=pre[l]]=x;
Len[x]=l&&r?min (Inf,len[l]+len[r]-len[x]): INF;
Len[l]=len[r]=inf;
Q.push (MP (len[x],x));
printf ("%d\n", ans);
return 0;
}
Sentiment:
1. This problem is very ingenious in the way of thinking:
If you want to take a line segment at both ends of the line, then this line can not exist, so the length of the line into the left + right-the current segment;
And this idea for a number of line segments is also set up, we can combine a good number of segments together to see if the current segment is 3 line segments merged into: A+b-c, then left + right-the current line segment is equivalent to delete the a,b, and then the C "Resurrection"
2. The code is also very clever (Orz zyf-zyf)
For a line segment, record the left and right endpoints, pre[],ne[]; When you delete a point, you cannot remove it directly from the queue, then you assign the value to the INF, and when you remove it from the queue, the length in the queue does not match this value, and you skip directly.
3.UPD: In fact, it can be achieved by using set directly