题目大意:有个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;
}