比赛模考 2018.03.11 塞克斯斯

Posted oyiya

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了比赛模考 2018.03.11 塞克斯斯相关的知识,希望对你有一定的参考价值。

【问题描述】

塞克斯斯是六兄弟中的老六,他喜欢老大福斯特,他希望福斯特
高兴。所以他要帮福斯特写作业。作业如下:
给 n 个正方形,正方形有两种:
A 型:平行于坐标轴,中心位于(x,y),边长为偶数 a;
B 型:和坐标轴成 45 度夹角,中心位于(x,y),对角线长为偶数 d。
求这些正方形覆盖的面积总大小。

【输入格式】

第一行一个整数 n。
接下来 n 行每行描述一个正方形,共有一个字符和三个整数。如
果字符为 A 表示是 A 型正方形,接下来输入 x,y 和 a。如果字符为 B
表示是 B 型正方形,接下来输入 x,y 和 d。

【输出格式】

一行一个实数表示答案,保留 2 位小数。

【样例输入】

8
A -7 10 4
B 3 10 8
A -6 6 6
A -2 5 8
B 3 -1 8
B -7 -4 8
A 3 9 2
B 8 6 6

【样例输出】

205.50

【样例解释】

技术分享图片

【子任务】

数据保证|x|,|y|,a,d≤1000,且 a 和 d 一定为正偶数。
数据分为三个子任务。
子任务一:20 分,保证 n≤1000。
子任务二:30 分,保证 n≤200000,只有 A 型正方形。
子任务三:50 分,保证 n≤200000。

【正解】

因为坐标范围很小,所以就想能不能枚举格子统计面积
我们用点的坐标包括上它右上角的格子
对于A型矩形(正放的矩形),前缀和维护每个格子上被多少个矩形覆盖。所以对于每个矩形,在矩形的左下角的格子权值加一,矩形的左上角的上面一个格子和矩形的右下角的右边一个格子的权值各减一,矩形的右上角的右上角格子的权值加一。最后两个循环以前缀和的方式扫描过去,每个格子上的权值就是它被多少个矩形覆盖
对于B型矩形(斜放的矩形),一样用前缀和,只不过用另一个数组记录。并且我们把坐标系也斜过去,把斜过去之后的一单位长度定位原坐标系的\(\sqrt2\)长度,那么我们就发现原坐标系里的\((x,y)\)在新坐标系里的坐标是\((x+y,x-y)\)(根据点到直线的距离公式直接求)。
最后统一扫描的时候,先扫描B的前缀和,再在扫描A的前缀和的时候统计答案。我们把每个格子拆成四个三角形。如果这个格子在A的前缀和中已经被覆盖过了,那么\(ans\)直接加4。否则找它斜过去后对应的B的前缀和中的四个格子,有多少格子被覆盖,那么\(ans\)加多少值
最后\(ans\)除4
(注意,因为B的坐标系的单位长度小,所以它的整个大小是A的坐标系的两倍)

#include<bits/stdc++.h>
#define ll long long
const int Abs=1500+10,MAXN=Abs<<1;
int s1[MAXN][MAXN],s2[MAXN<<1][MAXN<<1],n;
double ans;
template<typename T> inline void read(T &x)
{
    T data=0,w=1;
    char ch=0;
    while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
    if(ch=='-')w=-1,ch=getchar();
    while(ch>='0'&&ch<='9')data=((T)data<<3)+((T)data<<1)+(ch^'0'),ch=getchar();
    x=data*w;
}
template<typename T> inline void write(T x,char c='\0')
{
    if(x<0)putchar('-'),x=-x;
    if(x>9)write(x/10);
    putchar(x%10+'0');
    if(c!='\0')putchar(c);
}
template<typename T> inline void chkmin(T &x,T y){x=(y<x?y:x);}
template<typename T> inline void chkmax(T &x,T y){x=(y>x?y:x);}
template<typename T> inline T min(T x,T y){return x<y?x:y;}
template<typename T> inline T max(T x,T y){return x>y?x:y;}
int main()
{
    freopen("skss.in","r",stdin);
    freopen("skss.out","w",stdout);
    read(n);
    for(register int i=1;i<=n;++i)
    {
        char opt;
        std::cin>>opt;
        if(opt=='A')
        {
            int x,y,a;
            read(x);read(y);read(a);
            x+=Abs,y+=Abs;
            s1[x-(a>>1)][y-(a>>1)]++;
            s1[x-(a>>1)][y+(a>>1)]--;
            s1[x+(a>>1)][y-(a>>1)]--;
            s1[x+(a>>1)][y+(a>>1)]++;
        }
        if(opt=='B')
        {
            int x,y,d;
            read(x);read(y);read(d);
            int nx=x+y+MAXN,ny=x-y+MAXN;
            s2[nx-(d>>1)][ny-(d>>1)]++;
            s2[nx-(d>>1)][ny+(d>>1)]--;
            s2[nx+(d>>1)][ny-(d>>1)]--;
            s2[nx+(d>>1)][ny+(d>>1)]++;
        }
    }
    for(register int i=1;i<(MAXN<<1);++i)
        for(register int j=1;j<(MAXN<<1);++j)s2[i][j]+=s2[i-1][j]+s2[i][j-1]-s2[i-1][j-1];
    for(register int i=1;i<MAXN;++i)
        for(register int j=1;j<MAXN;++j)
        {
            s1[i][j]+=s1[i-1][j]+s1[i][j-1]-s1[i-1][j-1];
            if(s1[i][j])
            {
                ans+=4.0;
                continue;
            }
            int nx=i+j,ny=i-j+MAXN;
            if(s2[nx][ny])ans++;
            if(s2[nx+1][ny])ans++;
            if(s2[nx][ny-1])ans++;
            if(s2[nx+1][ny-1])ans++;
        }
    ans/=4.0;
    printf("%.2f\n",ans);
    return 0;
}

以上是关于比赛模考 2018.03.11 塞克斯斯的主要内容,如果未能解决你的问题,请参考以下文章

#2020上半年软考第一次模考大赛# 开考在即,来场考前热身

软考猛料2020软考生的重大福利:模考大赛知识合集有奖答题,全部免费参与

软考猛料2020软考生重大利好:模考大赛知识合集备考辅导有奖刷题,全部免费参与

官方模考?!ACT宣布启动PreACT考试

AI又对奥数下手,刷题刷出「模考」最好成绩

(C语言练习)假设某实验小组的5名学生,C语言模考成绩已给定(要求学生从外部键盘输入),现要求对其降序输出,并统计低于平均分的学生人数,并输出最高分和最低分。