POJ-2991 Crane(区间更新+向量旋转)

题目大意:n个向量首尾相连,每次操作使某个区间中的所有向量都旋转同样的角度。每次操作后都回答最后一个向量的坐标。

题目分析:区间维护向量信息。向量旋转:x1=x0*cos(t)-y0*sin(t),y1=x0*sin(t)+y0*cos(t),其中t为旋转的角度。

 

代码如下:

# include<iostream>
# include<cmath>
# include<algorithm>
# include<cstdio>
using namespace std;
# define mid (l+(r-l)/2)

const int N=10005;
const double PI=acos(-1.0);

double x[N<<2],y[N<<2];
int lazy[N<<2];
int angle[N];

inline void read(int &x)
{
	x=0;
	char c;
	while((c=getchar())&&(c<'0'||c>'9'));
	x=c-'0';
	while(c=getchar()){
		if(c<'0'||c>'9') break;
		x=x*10+c-'0';
	}
}

inline double f(int x)
{
	return x*PI/180.0;
}

inline void pushUp(int rt)
{
	x[rt]=x[rt<<1]+x[rt<<1|1];
	y[rt]=y[rt<<1]+y[rt<<1|1];
}

inline void pushDown(int rt)
{
	if(lazy[rt]==0) return ;
	lazy[rt<<1]+=lazy[rt];
	lazy[rt<<1|1]+=lazy[rt];
	
	double xx=x[rt<<1];
	double yy=y[rt<<1];
	x[rt<<1]=xx*cos(f(lazy[rt]))-yy*sin(f(lazy[rt]));
	y[rt<<1]=xx*sin(f(lazy[rt]))+yy*cos(f(lazy[rt]));
	
	xx=x[rt<<1|1];
	yy=y[rt<<1|1];
	x[rt<<1|1]=xx*cos(f(lazy[rt]))-yy*sin(f(lazy[rt]));
	y[rt<<1|1]=xx*sin(f(lazy[rt]))+yy*cos(f(lazy[rt]));
	lazy[rt]=0;
}

inline void build(int rt,int l,int r)
{
	lazy[rt]=0;
	if(l==r){
		x[rt]=0.0;
		int a;
		read(a);
		y[rt]=a;
	}else{
		build(rt<<1,l,mid);
		build(rt<<1|1,mid+1,r);
		pushUp(rt);
	}
}

inline void update(int rt,int l,int r,int L,int R,int a)
{
	if(L<=l&&r<=R){
		lazy[rt]+=a;
		double xx=x[rt];
		double yy=y[rt];
		x[rt]=xx*cos(f(a))-yy*sin(f(a));
		y[rt]=xx*sin(f(a))+yy*cos(f(a));
	}else{
		pushDown(rt);
		if(L<=mid) update(rt<<1,l,mid,L,R,a);
		if(R>mid) update(rt<<1|1,mid+1,r,L,R,a);
		pushUp(rt);
	}
}

int main()
{
	int n,m;
	bool first=true;
	while(~scanf("%d%d",&n,&m))
	{
		if(!first) puts("");
		first=false;
		build(1,0,n-1);
		for(int i=0;i<n;++i)
			angle[i]=180;
		int a,b;
		while(m--){
			scanf("%d%d",&a,&b);
			update(1,0,n-1,a,n-1,b-angle[a-1]);
			angle[a-1]=b;
			printf("%.2lf %.2lf\n",x[1],y[1]);
		}
	}
	return 0;
}

  

posted @ 2016-07-28 16:48  20143605  阅读(232)  评论(0编辑  收藏  举报