1. 程式人生 > >銀河戰艦

銀河戰艦

algorithm 操作 -s turn mat += 正常 坐標 區間

【問題描述】
瑞奧和瑪德利德是非常好的朋友。瑞奧平時的愛好是吹牛,瑪德利德的愛好是戳穿瑞奧吹的牛。
這天瑞奧和瑪德利德來到了宇宙空間站,瑞奧向瑪德利德炫耀這個空間站裏所有的銀河戰艦都是自己的。整個空間站可以看成一個無限大的二維平面,而每個戰艦都可以看做一個點,在空間站中一共分布著N艘銀河戰艦。
瑪德利德:“你說這些都是你的,那你讓他們動一動啊”
瑞奧:“誒你看,那艘動了!”
瑪德利德:“操作指令由我來發,一共有5種動的方法……”
瑞奧:“我覺得這樣有失公正……”
【輸入格式】
第一行一個正整數N,表示戰艦的數量
接下來N行,每行兩個實數,代表第i個戰艦的x,y坐標
然後一個正整數M,代表調度的次數
接下來M行操作,每個操作都是如下類型的一種:
M l r p q:把編號在[l,r]區間內的戰艦x坐標加上p,y坐標加上q
X l r:把編號在[l,r]區間內的戰艦沿x軸翻轉
Y l r:把編號在[l,r]區間內的戰艦沿y軸翻轉
O l r:把編號在[l,r]區間內的戰艦沿直線y=x翻轉
R l r a:把編號在[l,r]區間內的戰艦繞原點逆時針旋轉a°
【輸出格式】
輸出包括N行,代表著N艘戰艦經過M次調度之後的坐標(保留兩位小數)
【樣例輸入】
3
1 2
-2 2.5
0 -3
3
X 1 3
M 1 3 3 6
R 1 3 90
【樣例輸出】
-4.00 4.00
-3.50 1.00
-9.00 3.00

用正常的線段樹操作可以拿下M,X,Y,O操作大概是70分

但是R操作似乎無法實現

但此題我們發現它是離線的

那麽只要有最後結果就行了

值得一提的是R操作(x,y)->(xcosa-ysina,xsina+ycosa)

用矩陣就可以了,轉移矩陣:

cosa sina 0

-sina cosa 0

0 0 1

其實其他操作都可以用矩陣(上面矩陣不然為什麽是3×3?)

假設狀態(x,y,1),那麽M操作轉移矩陣:

1 0 0

0 1 0

p q 1

1這個就是用來轉移M操作的,那麽其他操作也很簡單了

用線段樹維護矩陣標記,並下傳就行了

#include<iostream>
#include
<cstdio> #include<cstring> #include<algorithm> #include<cmath> using namespace std; struct Matrix { double a[3][3]; Matrix() { memset(a,0,sizeof(a)); a[0][0]=1;a[1][1]=1;a[2][2]=1; } }Mat,c[400001],st; double x[100001],y[100001]; char s[10001]; int n,m; Matrix
operator *(const Matrix &x,const Matrix &y) { Matrix res; int i,j,k; memset(res.a,0,sizeof(res.a)); for (j=0;j<=2;j++) { for (k=0;k<=2;k++) if (y.a[k][j]) { for (i=0;i<=2;i++) { res.a[i][j]+=x.a[i][k]*y.a[k][j]; } } } return res; } void pushdown(int rt) { c[rt*2]=c[rt*2]*c[rt]; c[rt*2+1]=c[rt*2+1]*c[rt]; c[rt]=st; } void update(int rt,int l,int r,int L,int R) { if (l>=L&&r<=R) { c[rt]=c[rt]*Mat; return; } pushdown(rt); int mid=(l+r)/2; if (L<=mid) update(rt*2,l,mid,L,R); if (R>mid) update(rt*2+1,mid+1,r,L,R); } void dfs(int rt,int l,int r) { if (l==r) { printf("%.2lf %.2lf\n",x[l]*c[rt].a[0][0]+y[l]*c[rt].a[1][0]+c[rt].a[2][0],y[l]*c[rt].a[1][1]+x[l]*c[rt].a[0][1]+c[rt].a[2][1]); return; } pushdown(rt); int mid=(l+r)/2; dfs(rt*2,l,mid); dfs(rt*2+1,mid+1,r); } int main() {int i,j,l,r; double p,q,a; cin>>n; for (i=1;i<=n;i++) { scanf("%lf%lf",&x[i],&y[i]); } cin>>m; for (i=1;i<=m;i++) { scanf("%s",s); scanf("%d%d",&l,&r); if (s[0]==M) { scanf("%lf%lf",&p,&q); memset(Mat.a,0,sizeof(Mat.a)); Mat.a[0][0]=1;Mat.a[2][0]=p;Mat.a[1][1]=1;Mat.a[2][1]=q; Mat.a[2][2]=1; update(1,1,n,l,r); } if (s[0]==X) { memset(Mat.a,0,sizeof(Mat.a)); Mat.a[1][1]=-1;Mat.a[0][0]=1;Mat.a[2][2]=1; update(1,1,n,l,r); } if (s[0]==Y) { memset(Mat.a,0,sizeof(Mat.a)); Mat.a[1][1]=1;Mat.a[0][0]=-1;Mat.a[2][2]=1; update(1,1,n,l,r); } if (s[0]==O) { memset(Mat.a,0,sizeof(Mat.a)); Mat.a[1][0]=1;Mat.a[0][1]=1;Mat.a[2][2]=1; update(1,1,n,l,r); } if (s[0]==R) { memset(Mat.a,0,sizeof(Mat.a)); scanf("%lf",&a); Mat.a[0][0]=Mat.a[1][1]=cos(a*acos(-1)/180); Mat.a[0][1]=sin(a*acos(-1)/180); Mat.a[1][0]=-sin(a*acos(-1)/180); Mat.a[2][2]=1; update(1,1,n,l,r); } } dfs(1,1,n); }

銀河戰艦