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

时间:2023-03-08 20:40:23
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;
}