题目大意:
有N根棍子首尾相连,每次更改两个棍子之间的夹角,求最后一个点坐标。
解题思路:
因为前面的角度变了后面的角度也会变,所以显然是个线段树。
但是因为涉及到一点几何知识,我这种智障还是想了蛮久的。
#include<cstdio> #include<cstring> #include<cmath> #define LL long long #define db double #define maxn 10010 #define PI acos(-1.0) #define eps 1e-9 using namespace std; struct point{ double x,y; }p[maxn<<2]; int lazy[maxn<<2],angle[maxn]; int max(int x,int y){ if (x>y) return x; else return y; } int min(int x,int y){ if (x<y) return x; else return y; } void work(int a,int rt){ db x=p[rt].x; db y=p[rt].y; db ang=PI/180*a; p[rt].x=cos(ang)*x-sin(ang)*y; p[rt].y=sin(ang)*x+cos(ang)*y; } void pushup(int rt){ p[rt].x=p[rt<<1].x+p[rt<<1|1].x; p[rt].y=p[rt<<1].y+p[rt<<1|1].y; } void pushdown(int rt){ if (lazy[rt]){ work(lazy[rt],rt<<1); work(lazy[rt],rt<<1|1); lazy[rt<<1]+=lazy[rt]; lazy[rt<<1|1]+=lazy[rt]; lazy[rt]=0; } } void build(int l,int r,int rt){ if (l==r){ scanf("%lf",&p[rt].y); p[rt].x=0; return; } int mid=l+r>>1; build(l,mid,rt<<1); build(mid+1,r,rt<<1|1); pushup(rt); } void update(int a,int L,int R,int l,int r,int rt){ if (L<=l && r<=R){ lazy[rt]+=a; work(a,rt); return ; } pushdown(rt); int mid=(l+r)>>1; if (L<=mid) update(a,L,R,l,mid,rt<<1); if (R>mid) update(a,L,R,mid+1,r,rt<<1|1); pushup(rt); } int main(){ int n,m; int cnt=0; while (scanf("%d%d",&n,&m)==2){ if (cnt++) puts(""); build(1,n,1); for (int i=1;i<=n;i++) angle[i]=180; memset(lazy,0,sizeof(lazy)); while (m--) { int s,a; scanf("%d%d",&s,&a); int x=(a-angle[s]+360)%360; update(x,s+1,n,1,n,1); angle[s]=a; printf("%.2lf %.2lf\n",p[1].x+eps,p[1].y+eps); } } return 0; }