计蒜客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);
}

 

posted @ 2017-09-09 15:32  Z-Y-Y-S  阅读(733)  评论(0编辑  收藏  举报