计蒜客NOIP模拟赛(2) D2T3 银河战舰
【问题描述】
瑞奥和玛德利德是非常好的朋友。瑞奥平时的爱好是吹牛,玛德利德的爱好是戳穿瑞奥吹的牛。
这天瑞奥和玛德利德来到了宇宙空间站,瑞奥向玛德利德炫耀这个空间站里所有的银河战舰都是自己的。整个空间站可以看成一个无限大的二维平面,而每个战舰都可以看做一个点,在空间站中一共分布着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); }