首页 > 其他分享 >GYM 104128 M

GYM 104128 M

时间:2023-09-09 15:33:57浏览次数:45  
标签:return Point int double GYM operator const 104128

M. Drain the Water Tank

这道题需要用到向量间的叉积运算。

首先输入所有点,储存在数组\(a\)中,并将其全部转化为向量,储存在数组\(b\)中。

为了排尽水箱里的所有水,需要找到每一个属于水箱内容物局部最低块中的一个点。

所以可以将判断分为两步

  1. 判断是否为局部最低点:当\(b[i].y < 0\)且\(b[i + 1].y>0\)时,\(b[i]\)的终点即为局部最低点。但是,会有\(\searrow\)___\(\nearrow\)的情况,所以可以改为\(b[i].y <= 0\)且\(b[i + 1].y>0\),\(b[i]\)的终点作为整个局部的最低点。
  2. 判断是否为水箱内容物的最底部,因为题目是逆时针给出各点的,所以当\(b[i]\times b[i + 1]>0\)且满足①时,需要在\(b[i]\)的终点处挖洞。

按照以上方法,该题会Wa30

代码(Wa30)

#include <bits/stdc++.h>
#define endl '\n'
using namespace std;
typedef long long ll;
typedef pair<ll, ll> PII;

const double eps = 1e-8;
const double PI = acos(-1.0);

int sgn(double x)
{
    if (fabs(x) < eps)
        return 0;
    if (x < 0)
        return -1;
    else
        return 1;
}

struct Point
{
    int x, y;
    Point(){}
    Point(double _x, double _y) : x(_x), y(_y){}
    Point operator+(const Point &b) const{return Point(x + b.x, y + b.y);}
    Point operator-(const Point &b) const{return Point(x - b.x, y - b.y);}
    
    double operator^(const Point &b) const{return (x * b.y - y * b.x);}     //叉乘
    double operator*(const Point &b) const{return (x * b.x + y * b.y);}     //点乘

    bool operator<(const Point &b) const{return x < b.x || x == b.x && y < b.y;}
    bool operator==(const Point &b) const{return !sgn(x - b.x) && !sgn(y - b.y);}

    Point rotate(Point p, double B)
    {
        Point tmp;
        tmp.x = (x - p.x) * cos(B) - (y - p.y) * sin(B) + p.x;
        tmp.y = (x - p.x) * sin(B) + (y - p.y) * cos(B) + p.y;
        return tmp;
    }
};

const int N = 2e3 + 10;
int n;
Point a[N];
vector<Point> b;
signed main()
{
    std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    cin >> n;
    for(int i = 0;i < n;i++)
    {
        int x, y;
        cin >> a[i].x >> a[i].y;
    }
    a[n] = a[0];
    for(int i = 0;i < n;i++)
    {
        b.push_back(a[i + 1] - a[i]);
    }
    b[n] = b[0];
    int ans = 0;
    for(int i = 0;i < n;i++)
    {
        if((b[i] ^ b[i + 1]) > 0 && b[i].y <= 0 && b[i + 1].y > 0)
        {
            ans++;
        }
    }
    cout << ans;
    return 0;
}

因为上面的方法在遇到楼梯式的点时会把每一个→↑的点当作局部最低点,所以要先将向量的数组复制一倍,然后找到\(y<0\)的向量并从该向量开始遍历,新增一个变量\(fu\),每遇到一个\(y<0\)的向量都将\(fu = true\),当满足上面的①、②且\(fu=true\)时才挖洞,并把\(fu\)赋值为\(false\)。

这样又会得到一份Wa83的代码

代码(Wa83)

#include <bits/stdc++.h>
#define endl '\n'
using namespace std;
typedef long long ll;
typedef pair<ll, ll> PII;

const double eps = 1e-8;
const double PI = acos(-1.0);

int sgn(double x)
{
    if (fabs(x) < eps)
        return 0;
    if (x < 0)
        return -1;
    else
        return 1;
}

struct Point
{
    int x, y;
    Point(){}
    Point(double _x, double _y) : x(_x), y(_y){}
    Point operator+(const Point &b) const{return Point(x + b.x, y + b.y);}
    Point operator-(const Point &b) const{return Point(x - b.x, y - b.y);}
    
    double operator^(const Point &b) const{return (x * b.y - y * b.x);}     //叉乘
    double operator*(const Point &b) const{return (x * b.x + y * b.y);}     //点乘

    bool operator<(const Point &b) const{return x < b.x || x == b.x && y < b.y;}
    bool operator==(const Point &b) const{return !sgn(x - b.x) && !sgn(y - b.y);}

    Point rotate(Point p, double B)
    {
        Point tmp;
        tmp.x = (x - p.x) * cos(B) - (y - p.y) * sin(B) + p.x;
        tmp.y = (x - p.x) * sin(B) + (y - p.y) * cos(B) + p.y;
        return tmp;
    }
};

const int N = 2e3 + 10;
int n;
Point a[N];
vector<Point> b;
signed main()
{
    //std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    cin >> n;
    for(int i = 0;i < n;i++)
    {
        int x, y;
        cin >> a[i].x >> a[i].y;
    }
    a[n] = a[0];
    for(int i = 0;i < n;i++)
    {
        b.push_back(a[i + 1] - a[i]);
    }
    b[n] = b[0];
    int ans = 0;
    int now = 0;
    b.insert(b.end(), b.begin(), b.end());
    for(now = 0;b[now].y >= 0;)
    {
        now++;
    }
    int xx = now;
    bool fu = 0;
    for(int i = now;i < now + n;i++)
    {
        //cout << xx << " " << (b[xx] ^ b[i]);
        if(b[i].y < 0)
        fu = 1;
        if((b[i] ^ b[i + 1]) > 0 && b[i].y <= 0 && b[i + 1].y > 0 && fu)
        {
            ans++;
            //cout << " ++";
            fu = 0;
        }
        //cout << endl;
    }
    cout << ans;
    return 0;
}

原因是没有考虑这个点的情况image-20230909152008454,所以要在满足条件①时也把\(fu\)赋值为\(false\)
时间复杂度为\(O(n)\)

正解代码

#include <bits/stdc++.h>
#define endl '\n'
using namespace std;
typedef long long ll;
typedef pair<ll, ll> PII;

const long double eps = 1e-8;
const long double PI = acos(-1.0);

ll sgn(long double x)
{
    if (fabs(x) < eps)
        return 0;
    if (x < 0)
        return -1;
    else
        return 1;
}

struct Point
{
    int x, y;
    Point() {}
    Point(long double _x, long double _y) : x(_x), y(_y) {}
    Point operator+(const Point &b) const { return Point(x + b.x, y + b.y); }
    Point operator-(const Point &b) const { return Point(x - b.x, y - b.y); }

    long double operator^(const Point &b) const { return (x * b.y - y * b.x); } // 叉乘
    long double operator*(const Point &b) const { return (x * b.x + y * b.y); } // 点乘

    bool operator<(const Point &b) const { return x < b.x || x == b.x && y < b.y; }
    bool operator==(const Point &b) const { return !sgn(x - b.x) && !sgn(y - b.y); }

    Point rotate(Point p, long double B)
    {
        Point tmp;
        tmp.x = (x - p.x) * cos(B) - (y - p.y) * sin(B) + p.x;
        tmp.y = (x - p.x) * sin(B) + (y - p.y) * cos(B) + p.y;
        return tmp;
    }
};

const ll N = 2e3 + 10;
ll n;
Point a[N];
vector<Point> b;
signed main()
{
    // std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    cin >> n;
    for (ll i = 0; i < n; i++)
    {
        ll x, y;
        cin >> a[i].x >> a[i].y;
    }
    a[n] = a[0];
    for (ll i = 0; i < n; i++)
    {
        b.push_back(a[i + 1] - a[i]);
    }
    b[n] = b[0];
    ll ans = 0;
    ll now = 0;
    b.insert(b.end(), b.begin(), b.end());
    for (now = 0; b[now].y >= 0;)
    {
        now++;
    }
    ll xx = now;
    bool fu = 0;
    for (ll i = now; i < now + n; i++)
    {
        // cout << xx << " " << (b[xx] ^ b[i]);
        if (b[i].y < 0)
            fu = 1;
        if (b[i].y <= 0 && b[i + 1].y > 0 && fu)
        {
            // cout << " ++";
            fu = 0;
            if((b[i] ^ b[i + 1]) > 0)
            {
                ans++;
            }
        }
        // cout << endl;
    }
    cout << ans;
    return 0;
}

标签:return,Point,int,double,GYM,operator,const,104128
From: https://www.cnblogs.com/tongluosao/p/17689526.html

相关文章

  • Gym102994M Travel Dream
    题意:\(n\)个点的图,找一个有\(k\)个点的的简单环,使其边权和最大。随机黑白染色,拆成两条颜色不同的不相交链,做\(300\)次即可。链的情况是好做的,做完后,预处理\(f_{x,y}\)表示\(x\)到\(y\)的最大距离,枚举两条端点颜色不同的边可以直接合并。链点数\(\leq4\)都是可以直......
  • 安装强化学习包gym报错问题及解决方法
    安装命令pipinstallgymnasium[all]如遇如下报错error:command'swig.exe'failed:Nosuchfileordirectory[endofoutput]note:Thiserrororiginatesfromasubprocess,andislikelynotaproblemwithpip.ERROR:Failedbuildingwheelfo......
  • Gym102354I From Modular to Rational
    问两个相乘不会炸\(\rmlong\long\)的质数,用CRT合并,得到\(\frac{p}{q}\equivr\\pmodM\)。其中\(M\)是大于\(10^{18}\)的数。由于这个\(M\)太大了,不存在\(\frac{p}{q}\equiv\frac{a}{b}\pmodM\)且\(p,q,a,b\leq10^9\),所以我们只需找到一个\(\frac{p}{......
  • CFgym103260K-Rectangle Painting
    前言断续地调了一天一夜,终于做出来了!题目链接-RectanglePainting大概就是:给\(n\)个集合\(S_i\),两种操作,1{[l,r],x}lr向\(S_l\)到\(S_r\)插入\(x\)2lr询问\(\max\limits_{i=l}^r\{\text{mex}(S_i)\}\)。但是强制在线!\(1\len,l,r\le2\times10^5,1\le......
  • Gym103687D The Profiteer:回滚莫队信息双指针可以做到线性对数
    标题写得好所谓的回滚莫队信息意思是,设信息保存在两个大小分别为\(a,b\)的结构上,将这两个信息进行合并得到大小为\(a+b\)的信息需要的时间为\(\Omega(\min\{a,b\}\cdotf(n))\);而给定一个大小为\(1\)的信息,可以在\(\mathrmO(f(n))\)时间内将它加入到任何一个结构中......
  • Gym-103438C Werewolves
    Gym-103438CWerewolves题面有\(n(1\len\le3000)\)个节点的树,每个节点的颜色为\(c_i\)。请计算这个树存在多少不同的连通子图,满足这个连通子图中,存在某种颜色,其出现次数严格大于连通子图中节点数量的一半。简化题意first对于任意一个联通子图,如果该联通子图对答......
  • gym/10446/C. 0689
    C.0689我们考虑i作为左端点的贡献。我们强制翻转之后i这个点与原来不同,因为假如翻转之后i和原来相同,我们显然可以将这个翻转区间的左右端点往中间缩小1,也就是它会在更大的i被计算。另一个问题,对于同一个i,不同的右端点是否会使得翻转之后相同,这也是不会的,abab......
  • 【OpenAI】Python: 基于 Gym-CarRacing 的自动驾驶项目(2)| 车道检测功能的实现 | 边缘
        猛戳,跟哥们一起玩蛇啊! ......
  • Gym104128L Proposition Composition
    很好口胡却不好写。把边分成链边和额外边首先想到分类讨论,显然不能只删额外边,所以有两类情况,删一链边和两链边。如果删一链边,这一链边要么完全没被额外边覆盖,然后其他任选一条;要么被覆盖一次,额外边选覆盖它的边。用线段树简单维护即可。现在难的是删两链边,且这两条链边都至少......
  • Gym103687K Dynamic Reachability
    一个很奇妙的题。回想起之前打的一场模拟赛,有一道题的部分问题是要维护动态图两两联通性的。可能不太一样,但是他有一个离线的思想,将没有修改过的边提前拎出来,把已知的联通性先求了,再用线段树分治一类的可撤销做法维护剩下边的修改。但是这样维护的复杂度跟修改次数相关非常大,如果......