Time Limit: 2000MS | Memory Limit: 65536K | |||
Total Submissions: 4895 | Accepted: 1313 | Special Judge |
Description
Input
Output
Sample Input
2 1
10 5
1 90
3 2
5 5 5
1 270
2 90
Sample Output
5.00 10.00
-10.00 5.00
-5.00 10.00
题意:n条线段首位相连,从1到n依次从下到上比值连接,指向上方,第i条线段的长度为Li。 有C条指令。指令i给出两个整数Si和Ai,效果是使得线段Si和Si+1之间的角度变成Ai度。其中角度指的是Si开始沿逆时针方向旋转到Si+1所经过的角度。最开始时左右角度都是180度。 在执行每条指令后,输出此时第N条线段的端点的坐标。设第一条线段的下端点坐标为 (0,0)。
题解:先我们了解一下两个基础的计算几何知识。
①:一个向量(x,y)沿逆时针方向旋转rad度后得到的向量为:
nx = x*cos(rad) - y*sin(rad) ny = x*sin(rad) - y*cos(rad)
注意:题中向量旋转的角度应该是 rad - degree[i](degree[i]表示Si与Si+1在此时的夹角)。
②:如果一个折线是由多条向量连接而成的,那么这条向量的终点坐标一定等于 起点+向量1+向量2+...+向量n 。
知道了这两个知识点,再回头看这道题目。我们建立一棵线段树,来维护两个信息:1. 节点区间[l,r]所表示的向量的x[i] 和 y[i]。 2. 每个节点区间[l,r]所表示的区间需要逆时针旋转的角度(在计算时候我们需要转化为弧度)。在每次转动时我们需要更新 ql到n这些线段的向量。我们在update函数中查找到大于等于ql的区间左端点,更新区间,更新完毕后,记录下旋转角度,并更新它的自区间,然后将记录下的角度值变为0。
具体见代码:
#include<cstdio> #include<cstdlib> #include<cstring> #include<cmath> #include<algorithm> using namespace std; #define maxn 10010 #define lson i*2,l,m #define rson i*2+1,m+1,r #define PI acos(-1.0) int d[maxn*4],degree[maxn]; double x[maxn*4],y[maxn*4]; void cal(int i,int de)//计算旋转后的向量 { double rad=PI*de/180.0; double nx=x[i]*cos(rad)-y[i]*sin(rad); double ny=x[i]*sin(rad)+y[i]*cos(rad); x[i]=nx; y[i]=ny; } void PushUp(int i)//更新父区间 { x[i]=x[i*2]+x[i*2+1]; y[i]=y[i*2]+y[i*2+1]; } void PushDown(int i)//更新子区间 { if(d[i]) { d[i*2]+=d[i];//记录转动的角度 d[i*2+1]+=d[i]; cal(i*2,d[i]); cal(i*2+1,d[i]); d[i]=0;//更新完子区间后,父区间转动角度还原 } } void build(int i,int l,int r) { d[i]=0; if(l==r) { x[i]=0; scanf("%lf",&y[i]); return ; } int m=(l+r)/2; build(lson); build(rson); PushUp(i); } void update(int ql,int rad,int i,int l,int r) { if(ql<=l) { cal(i,rad); d[i]+=rad;//记录下当前区间转动的角度,然后也将子区间所表示的线段转动同样的角度 return ; } PushDown(i); int m=(l+r)/2; if(ql<=m) update(ql,rad,lson); update(ql,rad,rson); PushUp(i); } int main() { int n,m,i,sign=0; int ql,rad; while(scanf("%d%d",&n,&m)!=EOF) { if(sign) printf("\n"); sign=1; build(1,1,n); for(i=1;i<n;++i) degree[i]=180;//每两个相邻线段之间的初始角度都是180度 while(m--) { scanf("%d%d",&ql,&rad); update(ql+1,rad-degree[ql],1,1,n); degree[ql]=rad; printf("%.2lf %.2lf\n",fabs(x[1])<1e-8 ? 0:x[1],fabs(y[1])<1e-8 ? 0:y[1]); } } return 0; }