POJ 2991 Crane
线段树+计算几何,区间更新,区间求和,向量旋转。
/* *********************************************** Author :Zhou Zhentao Email :774388357@qq.com Created Time :2015/11/27 9:58:30 File Name :main.cpp ************************************************ */ #include <stdio.h> #include <string.h> #include <iostream> #include <algorithm> #include <vector> #include <queue> #include <set> #include <map> #include <string> #include <math.h> #include <stdlib.h> #include <time.h> using namespace std; const int maxn=10000+10; const double pi= acos(-1.0); struct SegTree { double SumX,SumY;//记录向量 int add;//延迟更新的标记,记录角度转变量 }st[maxn*4]; int f[maxn]; int N,Q; double H(double x) { return x*pi/180.0; } void Rot(int rt,double A) { double NewX,NewY; NewX=st[rt].SumX*cos(H(A))-st[rt].SumY*sin(H(A)); NewY=st[rt].SumX*sin(H(A))+st[rt].SumY*cos(H(A)); st[rt].SumX=NewX; st[rt].SumY=NewY; } void pushUp(int rt) { st[rt].SumX=st[rt*2].SumX+st[rt*2+1].SumX; st[rt].SumY=st[rt*2].SumY+st[rt*2+1].SumY; } void pushDown(int rt) { if(st[rt].add) { st[2*rt].add+=st[rt].add; st[2*rt+1].add+=st[rt].add; Rot(2*rt,(double)st[rt].add); Rot(2*rt+1,(double)st[rt].add); st[rt].add=0; } } void build(int l,int r,int rt) { st[rt].add=0; if(l==r) { scanf("%lf",&st[rt].SumY); st[rt].SumX=0; return; } int m=(l+r)/2; build(l,m,2*rt); build(m+1,r,2*rt+1); pushUp(rt); } void update(int L,int R,int add,int l,int r,int rt) { if(L<=l&&r<=R) { st[rt].add+=add; Rot(rt,(double)add); return; } pushDown(rt); int m=(l+r)/2; if(L<=m) update(L,R,add,l,m,2*rt); if(R>=m+1) update(L,R,add,m+1,r,2*rt+1); pushUp(rt); } int main() { int tot=0; while(~scanf("%d%d",&N,&Q)) { if(tot) printf("\n");tot=1; build(1,N,1); for(int i=1;i<=N;i++) f[i]=180; for(int i=1;i<=Q;i++) { int x;int y; scanf("%d%d",&x,&y); int A=y-f[x]; update(x+1,N,A,1,N,1); f[x]=y; printf("%.2lf %.2lf\n",st[1].SumX,st[1].SumY); } } return 0; }