POJ-2991 Crane(区间更新+向量旋转)
题目大意:n个向量首尾相连,每次操作使某个区间中的所有向量都旋转同样的角度。每次操作后都回答最后一个向量的坐标。
题目分析:区间维护向量信息。向量旋转:x1=x0*cos(t)-y0*sin(t),y1=x0*sin(t)+y0*cos(t),其中t为旋转的角度。
代码如下:
# include<iostream> # include<cmath> # include<algorithm> # include<cstdio> using namespace std; # define mid (l+(r-l)/2) const int N=10005; const double PI=acos(-1.0); double x[N<<2],y[N<<2]; int lazy[N<<2]; int angle[N]; inline void read(int &x) { x=0; char c; while((c=getchar())&&(c<'0'||c>'9')); x=c-'0'; while(c=getchar()){ if(c<'0'||c>'9') break; x=x*10+c-'0'; } } inline double f(int x) { return x*PI/180.0; } inline void pushUp(int rt) { x[rt]=x[rt<<1]+x[rt<<1|1]; y[rt]=y[rt<<1]+y[rt<<1|1]; } inline void pushDown(int rt) { if(lazy[rt]==0) return ; lazy[rt<<1]+=lazy[rt]; lazy[rt<<1|1]+=lazy[rt]; double xx=x[rt<<1]; double yy=y[rt<<1]; x[rt<<1]=xx*cos(f(lazy[rt]))-yy*sin(f(lazy[rt])); y[rt<<1]=xx*sin(f(lazy[rt]))+yy*cos(f(lazy[rt])); xx=x[rt<<1|1]; yy=y[rt<<1|1]; x[rt<<1|1]=xx*cos(f(lazy[rt]))-yy*sin(f(lazy[rt])); y[rt<<1|1]=xx*sin(f(lazy[rt]))+yy*cos(f(lazy[rt])); lazy[rt]=0; } inline void build(int rt,int l,int r) { lazy[rt]=0; if(l==r){ x[rt]=0.0; int a; read(a); y[rt]=a; }else{ build(rt<<1,l,mid); build(rt<<1|1,mid+1,r); pushUp(rt); } } inline void update(int rt,int l,int r,int L,int R,int a) { if(L<=l&&r<=R){ lazy[rt]+=a; double xx=x[rt]; double yy=y[rt]; x[rt]=xx*cos(f(a))-yy*sin(f(a)); y[rt]=xx*sin(f(a))+yy*cos(f(a)); }else{ pushDown(rt); if(L<=mid) update(rt<<1,l,mid,L,R,a); if(R>mid) update(rt<<1|1,mid+1,r,L,R,a); pushUp(rt); } } int main() { int n,m; bool first=true; while(~scanf("%d%d",&n,&m)) { if(!first) puts(""); first=false; build(1,0,n-1); for(int i=0;i<n;++i) angle[i]=180; int a,b; while(m--){ scanf("%d%d",&a,&b); update(1,0,n-1,a,n-1,b-angle[a-1]); angle[a-1]=b; printf("%.2lf %.2lf\n",x[1],y[1]); } } return 0; }