• 计蒜客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
    ",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);
    }
  • 相关阅读:
    Postgresql 常用操作
    捡回reset的未提交修改
    Excel 97-2003版本内部结构与查看方法
    【WPF】EntityframeworkCore Update注意事项
    Mac版StarUML破解方法
    Excel2016 自定义RTDServer添加方法
    apache中开启SSL设置方法
    软件开发中的常用工具
    编程风格统一配置EditorConfig
    Windows10简单启动项目添加方法
  • 原文地址:https://www.cnblogs.com/Y-E-T-I/p/7498359.html
Copyright © 2020-2023  润新知