您的位置:首页 > 理论基础 > 数据结构算法

SGU Ice-cream Tycoon 线段树+离散化

2014-05-05 18:56 295 查看
已单价划分区间,线段树节点保存数量和总价。优先处理单价较小的(即左节点)。

成段更新,延迟标记。这个题目存在卖与不卖两种情况,所以第一遍先查询一下到底能不能卖,如果能卖,再进行处理(下面代码的deal函数)。

因为数据范围很大,需要用__int64 保存,但是内存给的很小,所以我们需要离散化处理。把单价离散化,在具体计算的时候再搞回来。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define MAXN 400009
#define nmaxn 100009
#define LL __int64
struct node
{
bool col;
LL num;
LL tot;
} sum[MAXN];
LL se[nmaxn];
int k;
//离散化,二分查找
int sea(int l,int r,LL va)
{
while(l<=r)
{
int mid=(l+r)>>1;
if(se[mid]==va)return mid;
else if(se[mid]<va)l=mid+1;
else r=mid-1;
}
}
//向上更新
void update(int rt)
{
sum[rt].num=sum[rt<<1].num+sum[rt<<1|1].num;
sum[rt].tot=sum[rt<<1].tot+sum[rt<<1|1].tot;
}
//向下更新延迟标记
void downdate(int rt)
{
if(sum[rt].col==1)
{
sum[rt<<1].col=sum[rt<<1|1].col=1;
sum[rt].col=0;
sum[rt<<1].num=sum[rt<<1|1].num=0;
sum[rt<<1].tot=sum[rt<<1|1].tot=0;
}
return ;
}
//查询卖不卖
bool query(int l,int r,int rt,LL number,LL totsum)
{
if(totsum<0)return false;
if(sum[rt].num<number)return false;
else if(sum[rt].num==number&&sum[rt].tot>totsum)return false;
else if(sum[rt].num==number&&sum[rt].tot<=totsum)return true;
else
{
if(l==r)
{
if((LL)se[l]*number>totsum)return false;
else return true;
}
downdate(rt);
int m=(l+r)>>1;
if(sum[rt<<1].num>=number)return query(lson,number,totsum);
else return query(rson,number-sum[rt<<1].num,totsum-sum[rt<<1].tot);
}
}
//如果能卖,把相应的东西卖掉,加入在【l,r】的单价范围内都能卖,那么在这段线段树上进行延时标记
void deal(int l,int r,int rt,LL number,LL totsum)
{
if(number==0||totsum<=0)return ;
if(l==r)
{
sum[rt].num-=number;
sum[rt].tot-=(LL)se[l]*number;
return;
}
int m=(l+r)>>1;
downdate(rt);
if(sum[rt<<1].num>number)deal(lson,number,totsum);
else
{
sum[rt<<1].col=1;
deal(rson,number-sum[rt<<1].num,totsum-sum[rt<<1].tot);
sum[rt<<1].num=sum[rt<<1].tot=0;
}
update(rt);
return ;
}
//进货的情况 在单价为p的叶子节点上更新信息
void add(int l,int r,int rt,int p,LL number)
{
if(l==r)
{
sum[rt].num+=number;
sum[rt].tot+=(LL)se[p]*number;
return ;
}
downdate(rt);
int m=(l+r)>>1;
if(m>=p)add(lson,p,number);
else add(rson,p,number);
update(rt);
return ;
}
//建树,初始化线段树
void build(int l,int r,int rt)
{
if(l==r)
{
sum[rt].col=sum[rt].num=sum[rt].tot=0;
return ;
}
int m=(l+r)>>1;
build(lson);
build(rson);
update(rt);
}
LL y[nmaxn],x[nmaxn];
char s1[nmaxn][30];
int main()
{
LL n,m,i,j,z;
int num=1;
build(1,nmaxn,1);
i=0;
while(scanf("%s%I64d%I64d",s1[i],&x[i],&y[i])!=-1)
{
//离散化单价
if(strcmp(s1[i],"ARRIVE")==0)
{
se[num++]=y[i];
}
i++;
}
z=i;
//离散化
sort(se+1,se+num);
k=1;
for(i=2; i<num; i++)
{
if(se[i]!=se[i-1])se[++k]=se[i];
}
//依次输出结果
for(i=0; i<z; i++)
{
if(strcmp(s1[i],"ARRIVE")==0)
{
int temy=sea(1,k,y[i]);
add(1,nmaxn,1,temy,x[i]);
}
else
{
if(query(1,nmaxn,1,x[i],y[i]))
{
printf("HAPPY\n");
deal(1,nmaxn,1,x[i],y[i]);
}
else printf("UNHAPPY\n");
}
}
return 0;
}
感谢ink同学的无私帮助
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息