看完题目以后相信学过线段树的人大概就知道了,这是一个线段树的题目。每次改变一下夹角,就是把后面所有的杆的方向都改变了,如果把每个杆看成一个向量,就相当于这个向量旋转了一样。
一个向量(x,y)逆时针旋转a度后,该向量变为:(x*cosa-y*sina,x*sina+y*cosa)(我的代码里写的是顺时针旋转,一样的,只要把a变为-a就可以了)
#i nclude <iostream>
#i nclude <cmath>
#i nclude <cstdio>
#define maxn 10110
#define Cur int rt,int l,int r
#define Now int L,int R,int v
#define lson rt<<1,l,mid
#define rson rt<<1|1,mid+1,r
#define getmid int mid=(l+r)>>1
#define PI 3.14159265358979323846
#define exp 1e-9
using namespace std;
double x[4*maxn],y[4*maxn],Si[360],Co[360];
int deg[4*maxn],L[maxn],n,m,angle[maxn];
void build(Cur)
{
deg[rt]=0;
x[rt]=0;
if (l==r)
{
y[rt]=L[l];
return;
}
getmid;
build(lson);
build(rson);
y[rt]=y[rt<<1]+y[rt<<1|1];
}
void rot(int rt,int degree)
{
double tepx=x[rt],tepy=y[rt];
x[rt]=tepx*Co[degree]+tepy*Si[degree];
y[rt]=tepy*Co[degree]-tepx*Si[degree];
}
void PushDown(int rt)
{
if (deg[rt]==0) return;
rot(rt<<1,deg[rt]);
rot(rt<<1|1,deg[rt]);
deg[rt<<1]=deg[rt<<1]+deg[rt];
deg[rt<<1|1]=deg[rt<<1|1]+deg[rt];
while (deg[rt<<1]>=360) deg[rt<<1]-=360;
while (deg[rt<<1|1]>=360) deg[rt<<1|1]-=360;
deg[rt]=0;
}
void ***(Cur,Now)
{
if (L<=l && R>=r)
{
rot(rt,v);
deg[rt]=(deg[rt]+v);
while (deg[rt]>=360) deg[rt]-=360;
return;
}
PushDown(rt);
getmid;
if (L<=mid) ***(lson,L,R,v);
if (R> mid) ***(rson,L,R,v);
x[rt]=x[rt<<1]+x[rt<<1|1];
y[rt]=y[rt<<1]+y[rt<<1|1];
}
int main()
{
int si,ai,cas=0,tmp;
for (int i=0; i<=360; i++)
Si[i]=sin((i/180.0)*PI),Co[i]=cos((i/180.0)*PI);
while (scanf("%d%d",&n,&m)==2)
{
for (int i=1; i<n; i++) angle[i]=180;
if (cas++) printf("\n");
for (int i=1; i<=n; i++) scanf("%d",&L[i]);
build(1,1,n);
while (m--)
{
scanf("%d%d",&si,&ai);
tmp=angle[si]-ai;
while (tmp<0) tmp+=360;
while (tmp>=360) tmp-=360;
***(1,1,n,si+1,n,tmp);
printf("%.2lf %.2lf\n",x[1]+exp,y[1]+exp);
angle[si]=ai;
}
}
return 0;
}