Problem solving Report of line tree and monotonous queue optimization DP---POJ2373

Source: Internet
Author: User

The sprinkler head is installed on the grass (which can be regarded as a line segment) with the length of L (<= 1000000). The sprinkler is centered on this sprinkler head, and the spray radius of the sprinkler head is adjustable,

The adjustment range is [a, B]. Each vertex of the lawn must be covered by only one sprinkler, and some continuous intervals must be covered by one sprinkler,

Instead of being completely covered by multiple nozzle segments, the minimum number of sprinkler segments is obtained.

It is easy to think that this can be solved by using dp. The dp [I] is defined as the minimum number of sprinklers required to cover the range [0, I,

Dp [0] = 0, dp [I] = min {dp [I-2 * B]... dp [I-2 * a]}; because the nozzle is sprayed on both sides, so the length of a nozzle overwrite must be an even number,

Because the topic requires that the sprinkler cannot be sprayed outside [0, L], the subinterval [0, L '] with an odd length starting from 0 cannot be completely covered.

Another problem is that some continuous intervals must be covered by a certain sprinkler. How can this problem be solved. We can think like this,

If the interval [s, e] can only be overwritten by one sprinkler, The subinterval [0, M] (s <M <e) cannot be completely overwritten,

Because if [0, M] is completely overwritten, the [s, e] interval will be split, so we can mark the [s, e,

One of the more convenient encoding methods is to directly mark the dp array with a special value. My approach is as follows:

[Cpp]
Dp [0] = 0;
For (int I = 1; I <= l; I ++) dp [I] = inf;
For (int I = 0; I <n; I ++ ){
Int s, e;
Scanf ("% d", & s, & e );
For (int j = s + 1; j <e; j ++) dp [j] = inf + 1; // overwrite is not allowed with inf + 1
}

Complete code:
[Cpp]
# Include <cstdio>
# Include <cstring>
# Define L 1001000
 
Int a, B, n, l, inf, dp [L];
 
Int dpro (void)
{
If (B <1) return-1;
Dp [0] = 0;

For (int I = 2; I <= l; I + = 2)
{
If (dp [I] <= inf ){
Int min = inf;

For (int j = a; j <= B; j ++ ){
Int idx = I-2 * j;
If (idx <0) break;
If (min> dp [idx]) min = dp [idx];
}

Dp [I] = min + 1;
}
}
If (dp [l]> = inf) return-1;
Else return dp [l];
}
 
Int main ()
{
While (scanf ("% d", & n, & l )! = EOF ){

Scanf ("% d", & a, & B );
Inf = (l/a) + 9;
For (int I = 0; I <= l; I ++) dp [I] = inf;

For (int I = 0; I <n; I ++ ){
Int s, e;
Scanf ("% d", & s, & e );
For (int j = s + 1; j <e; j ++) dp [j] = inf + 1;
}

If (l & 1 = 1) printf ("-1 \ n ");
Else printf ("% d", dpro ());
}
Return 0;
}


From the above program, we can see that in the worst case, the time complexity is O (L ^ 2), and the range of L can reach 1 million,

So in extreme data, this program will time out, so we need to make some optimization on this program.

In the process of dp, the second layer for loop is used to find the minimum value of [I-2 * B, I-2 *,

This operation for finding the minimum value of a range can be optimized using the line segment tree. The optimized time complexity is O (LlgL ).


Code:

[Cpp]
# Include <cstdio>
# Include <cstring>
# Define L 1001000
 
Int a, B, n, l, inf, dp [L];
Int tree [4 * L];
 
Void updata (int * p, int rt, int l, int r, int pos, int k)
{
If (l = r ){
P [rt] = k;
Return;
}
Int mid = (l + r)> 1;
If (pos <= mid) updata (p, rt <1, l, mid, pos, k );
Else updata (p, rt <1 | 1, mid + 1, r, pos, k );
Int lv = p [rt <1];
Int rv = p [rt <1 | 1];
P [rt] = lv <rv? Lv: rv;
}
 
Int query (int * p, int rt, int l, int r, int s, int e)
{
If (l = s & e = r) return p [rt];
Int mid = (l + r)> 1;
If (e <= mid) return query (p, rt <1, l, mid, s, e );
If (s> mid) return query (p, rt <1 | 1, mid + 1, r, s, e );
Int lv = query (p, rt <1, l, mid, s, mid );
Int rv = query (p, rt <1 | 1, mid + 1, r, mid + 1, e );
Return lv <rv? Lv: rv;
}
 
Int dpro (void)
{
If (B <1) return-1;
Dp [0] = 0;
 
For (int j = 0; j <4 * L; j ++) tree [j] = L * 2;
 
For (int j = a; j <= B; j ++ ){
If (dp [2 * j] <= inf) dp [0 + 2 * j] = dp [0] + 1;
Updata (tree, 1, 1, l, j, dp [2 * j]);
}

For (int I = 2 * B + 2; I <= l; I + = 2)
{
Int min;
Int pos = (I> 1 );
Min = query (tree, 1, 1, l, pos-B, pos-);
 
If (dp [I] <= inf ){
// If (dp [I]> min + 1)
Dp [I] = min + 1;
Updata (tree, 1, 1, l, pos, dp [I]);
/* For (int j = a; j <= B; j ++ ){
Int idx = I-2 * j;
If (idx <0) break;
If (dp [I]> dp [idx] + 1) dp [I] = dp [idx] + 1;
}*/
}
}
If (dp [l]> = inf) return-1;
Else return dp [l];
}
 
Int main ()
{
While (scanf ("% d", & n, & l )! = EOF ){
 
Scanf ("% d", & a, & B );
Inf = (l/a) + 9;
For (int I = 0; I <= l; I ++) dp [I] = inf;
 
For (int I = 0; I <n; I ++ ){
Int s, e;
Scanf ("% d", & s, & e );
For (int j = s + 1; j <e; j ++) dp [j] = inf + 1;
}
 
If (l & 1 = 1) printf ("-1 \ n ");
Printf ("% d \ n", dpro ());
}
Return 0;
}

Another better optimization method is to use monotonous queue optimization:


Code:

[Cpp]
# Include <cstdio>
# Define L 1001000
 
Int a, B, n, l, inf, dp [L], queue [L], head, tail, size;
 
Void insert (int idx)
{
Tail ++;
While (head <tail & dp [queue [tail-1]> dp [idx]) tail --;
Queue [tail] = idx;
While (idx-queue [head]> = size) head ++;
}
 
Int dpro (void)
{
If (B <1) return-1;
Dp [0] = 0;
Size = 2 * B + 1;
Head = 0;
Tail =-1;

For (int I = a; I <= B; I ++) if (dp [2 * I] <= inf) dp [2 * I] = 1;
Int seg = 2 * B-2 *;
For (int I = 0; I <= seg; I + = 2) insert (I );

For (int I = 2 * B; I <= l; I + = 2)
{
If (I-a * 2> seg) insert (I-a * 2 );
While (I-queue [head]> = size) head ++;
If (dp [I] <= inf) dp [I] = dp [queue [head] + 1;
}

If (dp [l]> = inf) return-1;
Else return dp [l];
}
 
Int main ()
{
While (scanf ("% d", & n, & l )! = EOF ){

Scanf ("% d", & a, & B );
Inf = (l/a) + 9;
For (int I = 0; I <= l; I ++) dp [I] = inf;

For (int I = 0; I <n; I ++ ){
Int s, e;
Scanf ("% d", & s, & e );
For (int j = s + 1; j <e; j ++) dp [j] = inf + 1;
}

If (l & 1 = 1) printf ("-1 \ n ");
Else printf ("% d \ n", dpro ());
}
Return 0;
}

Author: sunny606

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.