题意:有N根杆子,前后两根杆子通过一个节点连接,每个节点可以旋转一定的角度,每次给你一个操作(s,a)表示将第S与S+1之间的角度修改为a度,并且每次操作之后都需要求出第N个节点的位置。
首先,最后一个节点的坐标(即位置)可以通过所有杆子末尾的坐标相加得到(这跟向量相加很类似)。因为每次更新需要修改S和S+1的位置,所以我们需要知道每次更新之后S和S+1的角度——查询操作,知道之后,再根据这次需要修改的角度a,得到S+1到最后一段杆子需要改变的角度——更新操作。最后输出答案即所以节点的x坐标和,y坐标和。线段树结点里的flag即是延迟标记。
#include <iostream> #include <cstring> #include <cstdio> #include <cmath> #define PI (acos(-1.0)) #define LL(x) (x<<1) #define RR(x) (x<<1|1) #define MID(a,b) (a+((b-a)>>1)) const int N=10010; using namespace std; struct node { int lft,rht; int flag,angle; double x,y; int mid(){return MID(lft,rht);} void fun(int valu) { flag=(flag+valu)%360; angle=(angle+valu)%360; double tmpx=x,tmpy=y; x=cos(valu/180.0*PI)*tmpx-sin(valu/180.0*PI)*tmpy; y=sin(valu/180.0*PI)*tmpx+cos(valu/180.0*PI)*tmpy; } }; int n,m; int len[N]; struct Segtree { node tree[N*4]; void up(int ind) { tree[ind].x=tree[LL(ind)].x+tree[RR(ind)].x; tree[ind].y=tree[LL(ind)].y+tree[RR(ind)].y; } void down(int ind) { if(tree[ind].flag) { tree[LL(ind)].fun(tree[ind].flag); tree[RR(ind)].fun(tree[ind].flag); tree[ind].flag=0; } } void build(int lft,int rht,int ind) { tree[ind].lft=lft; tree[ind].rht=rht; tree[ind].angle=tree[ind].flag=0; if(lft==rht) { tree[ind].x=0; tree[ind].y=len[lft]; } else { int mid=tree[ind].mid(); build(lft,mid,LL(ind)); build(mid+1,rht,RR(ind)); up(ind); } } void updata(int st,int ed,int ind,int valu) { int lft=tree[ind].lft,rht=tree[ind].rht; if(st<=lft&&rht<=ed) tree[ind].fun(valu); else { down(ind); int mid=tree[ind].mid(); if(st<=mid) updata(st,ed,LL(ind),valu); if(ed> mid) updata(st,ed,RR(ind),valu); up(ind); } } int query(int pos,int ind) { if(tree[ind].lft==tree[ind].rht) return tree[ind].angle; else { down(ind); int mid=tree[ind].mid(),ang; if(pos<=mid) ang=query(pos,LL(ind)); else ang=query(pos,RR(ind)); up(ind); return ang; } } }seg; int main() { int t_cnt=0; while(scanf("%d%d",&n,&m)!=EOF) { int s,a; for(int i=1;i<=n;i++) scanf("%d",&len[i]); seg.build(1,n,1); if(t_cnt++!=0) puts(""); for(int i=0;i<m;i++) { scanf("%d%d",&s,&a); int a1=seg.query(s,1); int a2=seg.query(s+1,1); int ang=(a-((180+a2-a1+360)%360))%360; seg.updata(s+1,n,1,ang); printf("%.2lf %.2lf\n",seg.tree[1].x,seg.tree[1].y); } } return 0; }