题目背景
广而告之:背景见其他L国的战斗!!大家一起刷
题目描述
这一次,L国决定军队分成n组,分布在各地,若以L国为原点,可以看作在一个直角坐标系内。但是他们都受统一的指挥,指令部共发出m个命令。命令有移动、上下转移和左右转移(瞬移??),但是由于某些奇奇怪怪的原因,军队收到命令总是有延迟,为了方便,军方已经写好一个栈(那还要我干嘛,自己都写好不就行了?),所以你要处理的顺序,应该是从后往前。
输入输出格式
输入格式:
输入文件army.in包括n+m+1行
第一行两个整数n、m
接下来n行
第i行有两个整数xi yi表示第i支军队的位置。
又是m行
每行首先是一个字符 C
若C为m 则紧跟两个整数 p q 表示把每支军队的位置从(xi,yi)移到(xi+p.yi+q)
若C为x 则表示把每支军队的位置从(xi,yi)移到(-xi,yi)
若C为y 则表示把每支军队的位置从(xi,yi)移到(xi,-yi)
输出格式:
输出文件army.out包含n行
第i行有两个整数xi、yi,表示第i支军队移动后的位置。
输入输出样例
3 3 0 0 4 -3 6 7 x m -1 2 y
1 2 -3 5 -5 -5
说明
对于30%的数据 1≤n≤1000 1≤m≤1000
对于100%的数据 1≤n≤500000 1≤m≤500000 Ai在longint范围内
———————————分割线———————————
终于……我还是写了一道矩阵的例题。废话不多说先来讲题吧。
首先我们可以将每一个点变成一个矩阵。

然后,这样子就是m的操作。

这样子就是x的操作。

同理这样就是y的操作。

所以!我们可以先将所有的操作先乘起来,最后得到一个矩阵和每一个点乘就可以了!
这样的话(这个话字我不知道打了几遍……每次都是跳出来haunted……)复杂度就能大大减少!
最后题目中倒序给出操作是为了方便我们计算!不用反过来的!设点的矩阵是A,操作(正序)分别有B,C,D。则乘的顺序一定是D*(C*(B*A))。所以结合律一用就是(D*C*B)*A。所以就不用反过来了!(之前被这个坑了很久……真的是智商捉急)。
#include<bits/stdc++.h>
using namespace std;
struct nob{
long long mat[4][4];
friend nob operator * (const nob &a,const nob &b){
nob rem;
for (int i=1; i<=3; i++){
for (int l=1; l<=3; l++){
long long sum=0;
for (int k=1; k<=3; k++){
sum+=a.mat[i][k]*b.mat[k][l];
}
rem.mat[i][l]=sum;
}
}
return rem;
}
}move[500005],ans;
struct point{
long long mat[4][2];
friend point operator * (const point &a,const nob b){
point rem;
for (int i=1; i<=3; i++){
long long sum=0;
for (int k=1; k<=3; k++){
sum+=a.mat[k][1]*b.mat[i][k];
}
rem.mat[i][1]=sum;
}
return rem;
}
}a[500005];
struct oper{
char ch;
long long x,y;
}b[500005];
int n,m;
nob add(long long aa,long long bb){
nob x;
x.mat[1][1]=1;x.mat[1][2]=0;x.mat[1][3]=aa;
x.mat[2][1]=0;x.mat[2][2]=1;x.mat[2][3]=bb;
x.mat[3][1]=0;x.mat[3][2]=0;x.mat[3][3]=1;
return x;
}
nob turn_x(){
nob x;
x.mat[1][1]=-1;x.mat[1][2]=0;x.mat[1][3]=0;
x.mat[2][1]=0;x.mat[2][2]=1;x.mat[2][3]=0;
x.mat[3][1]=0;x.mat[3][2]=0;x.mat[3][3]=1;
return x;
}
nob turn_y(){
nob x;
x.mat[1][1]=1;x.mat[1][2]=0;x.mat[1][3]=0;
x.mat[2][1]=0;x.mat[2][2]=-1;x.mat[2][3]=0;
x.mat[3][1]=0;x.mat[3][2]=0;x.mat[3][3]=1;
return x;
}
int main(){
for (int i=1; i<=3; i++){
for (int l=1; l<=3; l++){
if (i!=l) ans.mat[i][l]=0;
else ans.mat[i][l]=1;
}
}
cin>>n>>m;
for (int i=1; i<=n; i++){
cin>>a[i].mat[1][1]>>a[i].mat[2][1];
a[i].mat[3][1]=1;
}
for (int i=1; i<=m; i++){
cin>>b[i].ch;
if (b[i].ch=='m')
cin>>b[i].x>>b[i].y;
}
for (int i=1; i<=m; i++){
nob op;
if (b[i].ch=='x')
op=turn_x();
else if (b[i].ch=='y')
op=turn_y();
else op=add(b[i].x,b[i].y);
ans=ans*op;
}
for (int i=1; i<=n; i++){
a[i]=a[i]*ans;
cout<<a[i].mat[1][1]<<" "<<a[i].mat[2][1]<<endl;
}
return 0;
}
极其丑陋的代码