BZOJ 3938 Robot 线段树

38 篇文章 0 订阅

题目大意:给定n个点,每个点沿数轴匀速直线运动,多次改变某个点的速度和询问当前离数轴最远的点

标解见http://pan.baidu.com/share/link?shareid=4093182173&uk=2587171485#path=%252F%25E9%259B%2586%25E8%25AE%25AD%25E9%2598%259F%25E4%25BA%2592%25E6%25B5%258B%25202015%2520Round%2520%25231%2520%25E9%25A2%2598%25E8%25A7%25A3

我的做法是将时间放在x轴上,坐标放在y轴上,这样操作等价于插入线段和询问某一横坐标上的最大值

然后就是HEOI2013的Segment了。。。

时间复杂度O((n+C)*(logt)^2+Q*logt) 不是很卡啊= = 虽然比标解多了个log

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define M 700700
#define INF 0x3f3f3f3f3f3f3f3fll
using namespace std;

long long F(long long k,long long b,int x)
{
	return k*x+b;
}

long double Get_Intersection(long long k1,long long b1,long long k2,long long b2)
{
	return -(long double)(b1-b2)/(k1-k2);
}

struct Segtree{
	Segtree *ls,*rs;
	long long k,b;
	void* operator new (size_t)
	{
		#define L (1<<16)
		static Segtree *mempool,*C;
		if(C==mempool)
			mempool=(C=new Segtree[L])+L;
		C->ls=0x0;
		C->rs=0x0;
		C->k=0;
		C->b=-INF;
		return C++;
	}
	friend void Insert(Segtree *&p,int x,int y,int l,int r,long long k,long long b)
	{
		int mid=x+y>>1;
		if(!p) p=new Segtree;
		if(x==l&&y==r)
		{
			long long fx=F(p->k,p->b,x);
			long long fy=F(p->k,p->b,y);
			long long _fx=F(k,b,x);
			long long _fy=F(k,b,y);
			if( fx>=_fx && fy>=_fy )
				return ;
			if( fx<=_fx && fy<=_fy )
			{
				p->k=k;
				p->b=b;
				return ;
			}
			long double intersection=Get_Intersection(p->k,p->b,k,b);
			if(intersection<=mid+0.5)
			{
				if(fx>_fx)
					Insert(p->ls,x,mid,l,mid,p->k,p->b),p->k=k,p->b=b;
				else
					Insert(p->ls,x,mid,l,mid,k,b);
			}
			else
			{
				if(fy>_fy)
					Insert(p->rs,mid+1,y,mid+1,r,p->k,p->b),p->k=k,p->b=b;
				else
					Insert(p->rs,mid+1,y,mid+1,r,k,b);
			}
			return ;
		}
		if(r<=mid)
			Insert(p->ls,x,mid,l,r,k,b);
		else if(l>mid)
			Insert(p->rs,mid+1,y,l,r,k,b);
		else
			Insert(p->ls,x,mid,l,mid,k,b) , Insert(p->rs,mid+1,y,mid+1,r,k,b) ;
	}
	friend long long Get_Max(Segtree *p,int x,int y,int tim)
	{
		int mid=x+y>>1;
		if(!p) return -INF;
		if(x==y)
			return F(p->k,p->b,tim);
		if(tim<=mid)
			return max(F(p->k,p->b,tim),Get_Max(p->ls,x,mid,tim));
		else
			return max(F(p->k,p->b,tim),Get_Max(p->rs,mid+1,y,tim));
	}
}*tree1,*tree2;

struct Query{
	int type,tim;//0-modifiction 1-query
	long long k,b;
	int l,r;
}queries[M];

int n,m;

int last[100100];

int main()
{
	int i,x,y;
	char p[20];
	cin>>n>>m;
	for(i=1;i<=n;i++)
	{
		queries[i].type=0;
		queries[i].tim=0;
		scanf("%d",&x);
		queries[i].k=0;
		queries[i].b=x;
		queries[i].l=0;
		queries[i].r=1000000000;
		last[i]=i;
	}
	for(i=n+1;i<=n+m;i++)
	{
		scanf("%d%s",&queries[i].tim,p);
		if(p[0]=='q')
			queries[i].type=1;
		else
		{
			scanf("%d%d",&x,&y);
			queries[last[x]].r=queries[i].tim;
			queries[i].k=y;
			queries[i].b=F(queries[last[x]].k,queries[last[x]].b,queries[i].tim)-(long long)queries[i].tim*y;
			queries[i].l=queries[i].tim;
			queries[i].r=1000000000;
			last[x]=i;
		}
	}
	for(i=1;i<=m+n;i++)
	{
		if(queries[i].type==0)
		{
			Insert(tree1,0,1000000000,queries[i].l,queries[i].r,queries[i].k,queries[i].b);
			Insert(tree2,0,1000000000,queries[i].l,queries[i].r,-queries[i].k,-queries[i].b);
		}
		else
		{
			long long ans1=Get_Max(tree1,0,1000000000,queries[i].tim);
			long long ans2=Get_Max(tree2,0,1000000000,queries[i].tim);
			printf("%lld\n",max(abs(ans1),abs(ans2)));
		}
	}
	return 0;
}


评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值