LightOJ-2991-线段树

题目大意:有个n条线段组成的起重机,有m次询问,每次询问将第Si-Si+1之间的角度变为degree,问起点到终点的向量是多少;

题目解析:线段树好题,把它想象成一个一个区间[l,r],我们需要维护从l到r的向量和角度;如果我们要是一条折线旋转一个角度,就等于其中各个向量旋转一样的角度,还有一个细节就是线段树的懒操作(用到的时候我再更新)sd[];

AC代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#define PI acos(-1.0);
using namespace std;
const int maxn=10010;
int sd[maxn<<2],degree[maxn];
double sx[maxn<<2],sy[maxn<<2];
void roate(int n,int d)
{
	double deg=d* asin(1.0) /90.0;
	double x=cos(deg)*sx[n]-sin(deg)*sy[n];
	double y=sin(deg)*sx[n]+cos(deg)*sy[n];
	sx[n]=x;
	sy[n]=y;
}
void pushdown(int n)
{
	roate(n<<1,sd[n]);
	roate(n<<1|1,sd[n]);
	sd[n<<1]+=sd[n];
	sd[n<<1|1]+=sd[n];
	sd[n]=0;	
}
void pushup(int n)
{
	sx[n]=sx[n<<1]+sx[n<<1|1];
	sy[n]=sy[n<<1]+sy[n<<1|1];
}
void build(int l,int r,int n)
{
	sd[n]=0;
	if(l==r)
	{
		scanf("%lf",&sy[n]);
		sx[n]=0;
		return ;
	}
	int mid=(l+r)>>1;
	build(l,mid,n<<1);
	build(mid+1,r,n<<1|1);
	pushup(n);
}
void update(int p,int d,int l,int r,int n)
{
	if(p<l)
	{
		roate(n,d);
		sd[n]+=d;
		return ;
	}
	if(sd[n])	pushdown(n);
	int mid=(l+r)>>1;
	if(p<mid)	update(p,d,l,mid,n<<1);
	update(p,d,mid+1,r,n<<1|1);
	pushup(n);
}
int main()
{
	int n,m,flag=0,d,in,i;
	while(scanf("%d%d",&n,&m)!=EOF)
	{
		if(flag) puts("");
		else flag=1;
		build(1,n,1);
		for(i=1;i<=n;i++)
			degree[i]=180;
		while(m--)
		{
			scanf("%d%d",&in,&d);
			update(in,d-degree[in],1,n,1);
			degree[in]=d;
		 	printf("%.2lf %.2lf\n",fabs(sx[1])<1e-8?0:sx[1],fabs(sy[1])<1e-8?0:sy[1]);  
		}
	}
	return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值