Juice Extractor(树状数组 + dp)

  Juice Extractor 

Jerry loses himself in the interesting game: Fruit Ninja. Fruit Ninja is a game of iPhone and iPad in which the players cut the fruits coming from the bottom of the screen and gain the bonus from cutting more than two fruits with a single slice. Once a fruit is cut, it breaks into small pieces and cannot be cut any more.

After months of training, he becomes pro of this game. Actually, he can cut all the fruits on the screen at any time. Jerry also has a bad habit that he has no willing to leave some fruits for the future cutting. In the other words, after Jerry cuts the fruits, all the fruits on the screen breaks and no one left. That is why all his friends call him `Juice Extractor'.

Now he only consider about the bonus, when he cuts more than two fruits, he can gain some bonus scores as same as the number of fruits he slice at that time. For example, if Jerry cuts 4 fruits with a single slice, he can get 4 scores from this slice.

After Jerry gets the fruit schedule, he knows the appearing time and the disappearing time for every single fruit. He can only cut a fruit into pieces between its appearing time and disappearing time inclusive. He wants to know the maximum possible bonus scores he can receive.

 

Input 

There are several test cases; the first line of the input contains a single integer T, denoting the number of the test cases. (T200)

For each test case, the first line contains an integer N, denoting the total number of fruits. ( 1N1000)

The next N lines, each line describe a fruit. For each line, there are two integers Xi and Yi, where Xi is the appearing time of the fruit and Yi is the disappearing time of this fruit. ( 0XiYi1000000000)

 

Output 

For each test case, output a single integer denoting the maximum scores that Jerry could possibly gain. See the sample for further details.

 

Sample Input 

 

1
10
1 10
2 11
3 12
4 13
13 14
14 15
13 19
20 22
21 23
22 24

 

Sample Output 

 

 

Case #1: 10

 

     题意:

     给出 T组样例,每个样例都有一个 N,代表有 N 个水果。后给出每个水果出现的开始时间和结束时间。在任意一个时间点切水果的话,能够切到所有在这个时间出现的所有水果,当切的水果数 > 2 的时候,才会有得分,得分为所切的水果数,小于等于2得分为0。问如何切,使其分数达到最大。

 

     思路:

     DP + 树状数组。dp [ i ]  = max { dp [ t ] + point (t + 1, i) },dp [ i ] 代表在此刻切水果所达到的最大值,在 i 时刻这刀切的话,在 i 之前出现且尚未消失的水果都会被切除。

     同理 dp [ t ]  代表的也是 t 时刻前的水果都会消失,那么在 (t + 1 , i )这段时间内出现且尚未消失的水果将会在 i 这刀切下去的时候消失,所以最后的得分应该是 dp [ t ] + point ( t + 1, i ) 。

     预处理 dp 应该是只在该时刻切水果所得到的分数,用起点 + 1,(终点 + 1)-1,后 dp [ i ] += dp [ i - 1 ] 可以预处理出来。同时树状数组维护某段时间内的水果数。

 

     AC:

#include 
#include 
#include 
#include 
#include 

using namespace std;

const int MAX = 1005;

typedef struct {
    int l, r;
} node;

node no[MAX];
int ans;
int yy[MAX * 2];
int dp[MAX * 2];

int m;
int bit[MAX * 5];

int sum (int x) {
    int s = 0;
    while (x > 0) {
        s += bit[x];
        x -= x & -x;
    }

    return s;
}

void add (int i, int x) {
    while (i <= m) {
        bit[i] += x;
        i += i & -i;
    }
}

int main()
{
    int t;
    scanf("%d", &t);

    for (int tt = 1; tt <= t; ++tt) {
        int n;
        scanf("%d", &n);
        ans = 0;

        for (int i = 1; i <= n; ++i) {
            scanf("%d%d", &no[i].l, &no[i].r);
            yy[ans++] = no[i].l;
            yy[ans++] = no[i].r;
        }

        sort(yy, yy + ans);
        ans = unique(yy, yy + ans) - yy;

        m = ans * 5;
        memset(bit, 0, sizeof(bit));
        for (int i = 1; i <= n; ++i) {
            int s = lower_bound(yy, yy + ans, no[i].l) - yy;
            add(s + 1, 1);
        }

        memset(dp, 0, sizeof(dp));
        for (int i = 1; i <= n; ++i) {
            int s = lower_bound(yy, yy + ans, no[i].l) - yy;
            int e = lower_bound(yy, yy + ans, no[i].r) - yy;
            dp[s + 1] += 1;
            dp[e + 2] += -1;
        }

        for (int i = 1; i <= ans; ++i) dp[i] += dp[i - 1];

        for (int i = 1; i <= ans; ++i) {
            dp[i] = dp[i] > 2 ? dp[i] : 0;
        }

        for (int i = 1; i <= ans; ++i) {

            for (int j = 1; j < i; ++j) {
                int ans = sum(i) - sum(j);
                dp[i] = max(dp[i], dp[j] + (ans > 2 ? ans : 0));
            }

            for (int j = 1; j <= n; ++j) {
                int s =  lower_bound(yy, yy + ans, no[j].r) - yy;
                if (s + 1 == i) {
                    int e = lower_bound(yy, yy + ans, no[j].l) - yy;
                    add(e + 1, -1);
                }
            }

        }

        printf("Case #%d: ", tt);
        printf("%d\n", dp[ans]);
    }

    return 0;
}

  

 

你可能感兴趣的:(UVA)