首页 > ACM题库 > HDU-杭电 > HDU 2984-Jewel Trading-线段树-[解题报告]HOJ
2014
02-24

HDU 2984-Jewel Trading-线段树-[解题报告]HOJ

Jewel Trading

问题描述 :

You want to sell a diamond to a merchant for a good price. You know so much about how merchant likes the diamond that you have even built a mathematical model for it: He will definitely accept the price p if it’s not greater than a certain threshold a, but for a price p higher than it, he must have a think. The higher the price, the lower probability he will accept. Precisely, the probability that he accept price p > a is 1/(1 + (p – a)b) , where b > 1 is a positive constant in your model.

The exact trading process is as follows: you first propose a price (a non-negative integer), then the merchant decides whether to accept. If he accepts, the trade is over and you have no chance to regret. If he does not accept, you propose another price, and so on. You know that the merchant would get angry if you always propose unacceptable high prices, so you promised that the n -th proposal (if there is) is always not greater than a (which he can accept for sure).

Write a program to find an optimal way to propose prices to maximize your expected earning (i.e. the final price).

输入:

The input consists of several test cases. Each case is described by two positive integers n , a , and a real number b (1<=n<=100, 1<=a<=1000, 1 < b < 10) , b is given to up to three decimal places. The last test case is followed by a single zero, which should not be processed.

输出:

The input consists of several test cases. Each case is described by two positive integers n , a , and a real number b (1<=n<=100, 1<=a<=1000, 1 < b < 10) , b is given to up to three decimal places. The last test case is followed by a single zero, which should not be processed.

样例输入:

1 10 2 
10 33 3.14 
0

样例输出:

Case 1: 10.00 
Case 2: 34.41

Regional前最后一次做线段树了,这个题需要建立2*h-1棵线段树,复杂度( h^2*lg h )然后就是统计每棵线段树上的颜色种类,这题的坐标转换非常之麻烦。。。

 

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
bool flag[31];
int bound[210];
struct Seg
{
    int left,right,color;
} seg[210][210*4];
void build(int tree,int n,int left,int right)
{
    int mid = (left + right) / 2;
    seg[tree][n].left = left ;
    seg[tree][n].right = right ;
    seg[tree][n].color = 0 ;
    if(left == right)
        return ;
    build(tree,2*n,left,mid);
    build(tree,2*n+1,mid+1,right);
}
void insert(int tree,int n,int left,int right,int color)
{
    int mid = (seg[tree][n].left + seg[tree][n].right) / 2;
    if(seg[tree][n].left == left && seg[tree][n].right == right)
    {
        seg[tree][n].color = color;
    }
    else
    {
        if(seg[tree][n].color>=0)
        {
            seg[tree][2*n].color= seg[tree][n].color;
            seg[tree][2*n+1].color= seg[tree][n].color;
            seg[tree][n].color = -1;
        }
        if(right<=mid)
        {
            insert(tree,n*2,left,right,color);
        }
        else if(left>mid)
        {
            insert(tree,n*2+1,left,right,color);
        }
        else
        {
            insert(tree,n*2,left,mid,color);
            insert(tree,n*2+1,mid+1,right,color);
        }
    }
}
void query(int tree,int n,int left,int right)
{
    int mid = (seg[tree][n].left + seg[tree][n].right) / 2;
    if(seg[tree][n].color>=0)
    {
        flag[seg[tree][n].color] = true;
        return;
    }
    if(seg[tree][n].left == left && seg[tree][n].right ==right && seg[tree][n].color>=0)
    {
        flag[seg[tree][n].color] = true;
    }
    else
    {
        if(right<=mid)
        {
            query(tree,n*2,left,right);
        }
        else if(left>mid)
        {
            query(tree,n*2+1,left,right);
        }
        else
        {
            query(tree,n*2,left,mid);
            query(tree,n*2+1,mid+1,right);
        }
    }
}
 
int main()
{
    int h,n,k,x,y,v,s,cas=1;
    char ch;
    while(scanf("%d %d %d",&h,&n,&k)==3)
    {
        printf("Petri Dish #%d\n",cas++);
        int tree = 1;
        for(int i=h; i<2*h-1; i++)
        {
            bound[tree]=i;
            build(tree++,1,1,i);
        }
        for(int i=2*h-1; i>=h; i--)
        {
            bound[tree]=i;
            build(tree++,1,1,i);
        }
        while(n--)
        {
            scanf(" %c",&ch);
            if(ch == 'I')
            {
                scanf("%d %d %d %d",&x,&y,&v,&s);
                x++;
                y++;
                int left = x - s +1;
                for(int i=y-1; i>=y-s+1; i--)
                {
                    if(i < 1)
                        break;
                    if(i >=h)
                        left++;
                    int right = left + 2*s - 2- y +i;
                    if(right<1)
                        break;
                    insert(i,1,max(1,left),min(bound[i],right),v);
 
                }
                left = x - s +1;
                for(int i=y; i<=y+s-1; i++)
                {
                    if(i > 2*h-1)
                        break;
                    int right =  left + 2*s - 2+ y -i;
                    if(right<1)
                        break;
                    insert(i,1,max(1,left),min(bound[i],right),v);
                    if(i <h)
                        left++;
                }
            }
            else
            {
                scanf("%d %d %d",&x,&y,&s);
                memset(flag,0,sizeof(flag));
                int sum = 0;
                x++;
                y++;
                int left = x - s +1;
                for(int i=y-1; i>=y-s+1; i--)
                {
                    if(i < 1)
                        break;
                    if(i >=h)
                        left++;
                    int right = left + 2*s - 2- y +i;
                    if(right<1)
                        break;
                    query(i,1,max(1,left),min(bound[i],right));
 
                }
                left = x - s +1;
                for(int i=y; i<=y+s-1; i++)
                {
                    if(i > 2*h-1)
                        break;
                    int right =  left + 2*s - 2+ y -i;
                    if(right<1)
                        break;
                    query(i,1,max(1,left),min(bound[i],right));
                    if(i <h)
                        left++;
                }
                for(int i=1; i<=k; i++)
                {
                    if(flag[i])
                        sum++;
                }
                printf("%d\n",sum);
            }
        }
    }
    return 0;
}

解题参考:http://www.cnblogs.com/luyi0619/archive/2010/10/20/1856315.html