Description

Input
第一行 :一个整数N ,表示方案和询问的总数。
接下来N行,每行开头一个单词“Query”或“Project”。
若单词为Query,则后接一个整数T,表示Blue Mary询问第T天的最大收益。
若单词为Project,则后接两个实数SP,表示该种设计方案第一天的收益S,以及以后每天比上一天多出的收益P
1<=N<=1000001<=T<=500000<P<100|S|<=106
提示:本题读写数据量可能相当巨大,请选手注意选择高效的文件读写方式。

Output
对于每一个Query,输出一个整数,表示询问的答案,并精确到整百元(以百元为单位,
例如:该天最大收益为210290时,均应该输出2)。没有方案时回答询问要输出0

Sample Input
10
Project 5.10200 0.65000
Project 2.76200 1.43000
Query 4
Query 2
Project 3.80200 1.17000
Query 2
Query 3
Query 1
Project 4.58200 0.91000
Project 5.36200 0.39000

Sample Output
0
0
0
0
0

HINT

Source

思路
线段树标记永久化。见我的博客[Heoi2013]Segment

代码

#include <cstdio>

const int maxn=100000;
const int maxx=50000;

struct line
{
  double k,b;

  double f(int x)
  {
    return k*x+b;
  }
};

struct segment_tree
{
  int val[(maxx<<2)+10],totl;
  double topv;
  line li[maxn+10];

  int insert(int now,int left,int right,int insv)
  {
    if(left>right)
      {
        return 0;
      }
    int uol=li[insv].f(left)>li[val[now]].f(left);
    int uor=li[insv].f(right)>li[val[now]].f(right);
    int mid=(left+right)>>1;
    if((!val[now])||(uol&&uor))
      {
        val[now]=insv;
      }
    else if(uol^uor)
      {
        double c=(li[insv].b-li[val[now]].b)/(li[val[now]].k-li[insv].k);
        if((c<=mid)&&uol)
          {
            insert(now<<1,left,mid,insv);
          }
        else if((c<=mid)&&uor)
          {
            insert(now<<1,left,mid,val[now]);
            val[now]=insv;
          }
        else if((c>mid)&&uol)
          {
            insert(now<<1|1,mid+1,right,val[now]);
            val[now]=insv;
          }
        else if((c>mid)&&uor)
          {
            insert(now<<1|1,mid+1,right,insv);
          }
      }
    return 0;
  }

  inline int ins(double a,double b)
  {
    ++totl;
    li[totl].k=b;
    li[totl].b=a-b;
    insert(1,1,maxx,totl);
    return 0;
  }

  int query(int now,int left,int right,int pos)
  {
    double ff=li[val[now]].f(pos);
    if(ff>topv)
      {
        topv=ff;
      }
    if(left==right)
      {
        return 0;
      }
    int mid=(left+right)>>1;
    if(pos<=mid)
      {
        query(now<<1,left,mid,pos);
      }
    if(pos>mid)
      {
        query(now<<1|1,mid+1,right,pos);
      }
    return 0;
  }

  inline int ask(int p)
  {
    topv=0;
    query(1,1,maxx,p);
    int ans=topv/100;
    return ans;
  }
};

segment_tree st;
int n;
char s[10];

int main()
{
  scanf("%d",&n);
  while(n--)
    {
      scanf("%s",s);
      if(s[0]=='P')
        {
          double a,b;
          scanf("%lf%lf",&a,&b);
          st.ins(a,b);
        }
      else
        {
          int a;
          scanf("%d",&a);
          printf("%d\n",st.ask(a));
        }
    }
  return 0;
}