(中等) POJ 2991 Crane , 几何+线段树。
Description
ACM has bought a new crane (crane -- jeřáb) . The crane consists of n segments of various lengths, connected by flexible joints. The end of the i-th segment is joined to the beginning of the i + 1-th one, for 1 ≤ i < n. The beginning of the first segment is fixed at point with coordinates (0, 0) and its end at point with coordinates (0, w), where w is the length of the first segment. All of the segments lie always in one plane, and the joints allow arbitrary rotation in that plane. After series of unpleasant accidents, it was decided that software that controls the crane must contain a piece of code that constantly checks the position of the end of crane, and stops the crane if a collision should happen.
Your task is to write a part of this software that determines the position of the end of the n-th segment after each command. The state of the crane is determined by the angles between consecutive segments. Initially, all of the angles are straight, i.e., 180o. The operator issues commands that change the angle in exactly one joint.
Your task is to write a part of this software that determines the position of the end of the n-th segment after each command. The state of the crane is determined by the angles between consecutive segments. Initially, all of the angles are straight, i.e., 180o. The operator issues commands that change the angle in exactly one joint.
题意就是一个挖掘机,饿。。。吊车,的机械臂,有n节,可以转动,问每次转动之后最后一个位置。
刚开始的时候想到是用数组表示每一个点,然后用线段树更新某一个区间,但是超时了,因为每次更新都要让上一次更新全部更新彻底,其实就是直接全部更新,反而还不如直接模拟。后来看了看题解,提到向量。。。就是用数组记录区间内所有向量的和,那么所有区间的和就是答案,而且,每次旋转d度的话对这个区间也是旋转d度,没有区别。。。
另外被这个题坑了两个小时,还是今年的头两个小时。。。建树的时候没有更新彻底,看来以后自己测试一定要多组数据。。。。
代码如下:
#include<iostream> #include<cstdio> #include<cmath> #define lson L,M,po*2 #define rson M+1,R,po*2+1 using namespace std; struct state { double x,y; }; const double PI=atan2(1.0,1.0)*4; state BIT[10004*4]; int COL[10004*4]; int rang[10004]; void change(int po,int ct) { double tang; double len; tang=atan2(BIT[po].y,BIT[po].x); len=sqrt(BIT[po].x*BIT[po].x+BIT[po].y*BIT[po].y); tang+=ct*PI/180.0; BIT[po].x=len*cos(tang); BIT[po].y=len*sin(tang); } void pushUP(int po) { BIT[po].x=BIT[po*2].x+BIT[po*2+1].x; BIT[po].y=BIT[po*2].y+BIT[po*2+1].y; } void pushDown(int po) { if(COL[po]) { change(po*2,COL[po]); change(po*2+1,COL[po]); COL[po*2]+=COL[po]; COL[po*2+1]+=COL[po]; COL[po]=0; } } void build_tree(int L,int R,int po) { COL[po]=0; //DON'T FORGET !!! if(L==R) { int temp; BIT[po].x=0; COL[po]=0; scanf("%d",&temp); BIT[po].y=temp; return; } int M=(L+R)/2; build_tree(lson); build_tree(rson); pushUP(po); } void update(int ul,int ur,int ut,int L,int R,int po) { if(ul<=L&&ur>=R) { change(po,ut); COL[po]+=ut; COL[po]%=360; return; } pushDown(po); int M=(L+R)/2; if(ul<=M) update(ul,ur,ut,lson); if(ur>M) update(ul,ur,ut,rson); pushUP(po); } int main() { int n,c; int a,b; int cas=0; while(~scanf("%d %d",&n,&c)) { if(cas++) printf("\n"); build_tree(1,n,1); for(int i=1;i<=n;++i) rang[i]=0; for(int i=1;i<=c;++i) { scanf("%d %d",&a,&b); b-=180; if(b==-180) b=180; update(a+1,n,b-rang[a],1,n,1); rang[a]=b; printf("%.2lf %.2lf\n",BIT[1].x,BIT[1].y); } } return 0; }