2021洛谷10月月赛2游记

好久没写博客了,更一下吧。。

其实这场比赛个人感觉是比较考思维的,不过数据有点水。

总长 4 4 4 小时,满分 400 400 400 分,我打了 3 3 3 小时,拿了 300 300 300 分,就因有事走人了。

比较遗憾。

T1 『JROI-3』R.I.P.

签到题

O ( k n ) \mathcal{O}(k \sqrt n) O(kn )

C O D E CODE CODE

#include <bits/stdc++.h>
using namespace std;

#define int long long

int T, n, m;

namespace Fastio
{
    namespace Fread
    {
        const int SIZE = 1 << 21;
        char buf[SIZE], *S, *T;
        inline char getchar()
        {
            if (S == T)
            {
                T = (S = buf) + fread(buf, 1, SIZE, stdin);
                if (S == T)
                    return '\n';
            }
            return *S++;
        }
    } // namespace Fread
    namespace Fwrite
    {
        const int SIZE = 1 << 21;
        char buf[SIZE], *S = buf, *T = buf + SIZE;
        inline void flush()
        {
            fwrite(buf, 1, S - buf, stdout);
            S = buf;
        }
        inline void putchar(char c)
        {
            *S++ = c;
            if (S == T)
                flush();
        }
        struct NTR
        {
            ~NTR() { flush(); }
        } ztr;
    } // namespace Fwrite
#ifdef ONLINE_JUDGE
#define getchar Fread ::getchar
#define putchar Fwrite ::putchar
#endif
    struct Reader
    {
        template <typename T>
        Reader &operator>>(T &x)
        {
            char c = getchar();
            T f = 1;
            while (c < '0' || c > '9')
            {
                if (c == '-')
                    f = -1;
                c = getchar();
            }
            x = 0;
            while (c >= '0' && c <= '9')
            {
                x = x * 10 + (c - '0');
                c = getchar();
            }
            x *= f;
            return *this;
        }
        Reader &operator>>(char &c)
        {
            c = getchar();
            while (c == ' ' || c == '\n')
            {
                c = getchar();
            }
            return *this;
        }
        Reader &operator>>(char *str)
        {
            int len = 0;
            char c = getchar();
            while (c == ' ' || c == '\n')
            {
                c = getchar();
            }
            while (c != ' ' && c != '\n' && c != '\r')
            { // \r\n in windows
                str[len++] = c;
                c = getchar();
            }
            str[len] = '\0';
            return *this;
        }
        Reader() {}
    } cin;
    const char endl = '\n';
    struct Writer
    {
        template <typename T>
        Writer &operator<<(T x)
        {
            if (x == 0)
            {
                putchar('0');
                return *this;
            }
            if (x < 0)
            {
                putchar('-');
                x = -x;
            }
            static int sta[111];
            int top = 0;
            while (x)
            {
                sta[++top] = x % 10;
                x /= 10;
            }
            while (top)
            {
                putchar(sta[top] + '0');
                --top;
            }
            return *this;
        }
        Writer &operator<<(char c)
        {
            putchar(c);
            return *this;
        }
        Writer &operator<<(char *str)
        {
            int cur = 0;
            while (str[cur])
                putchar(str[cur++]);
            return *this;
        }
        Writer &operator<<(const char *str)
        {
            int cur = 0;
            while (str[cur])
                putchar(str[cur++]);
            return *this;
        }
        Writer() {}
    } cout;
#define cin Fastio ::cin
#define cout Fastio ::cout
#define endl Fastio ::endl
} // namespace Fastio

signed main()
{
    cin >> T;
    while (T--)
    {
        bool flag = 0;
        cin >> n >> m;
        for (register int i = sqrt(n); i >= 1; --i)
        {
            if (n % i == 0)
            {
                if (2 * (i + n / i + 2) <= m)
                {
                    puts("Good");
                    flag = 1;
                    break;
                }
            }
        }
        if (!flag)
            puts("Miss");
    }
}

T2 『JROI-3』黑白棋

一道简单的结论题。

C O D E CODE CODE

#include <bits/stdc++.h>
using namespace std;

#define int long long

namespace Fastio
{
    namespace Fread
    {
        const int SIZE = 1 << 21;
        char buf[SIZE], *S, *T;
        inline char getchar()
        {
            if (S == T)
            {
                T = (S = buf) + fread(buf, 1, SIZE, stdin);
                if (S == T)
                    return '\n';
            }
            return *S++;
        }
    } // namespace Fread
    namespace Fwrite
    {
        const int SIZE = 1 << 21;
        char buf[SIZE], *S = buf, *T = buf + SIZE;
        inline void flush()
        {
            fwrite(buf, 1, S - buf, stdout);
            S = buf;
        }
        inline void putchar(char c)
        {
            *S++ = c;
            if (S == T)
                flush();
        }
        struct NTR
        {
            ~NTR() { flush(); }
        } ztr;
    } // namespace Fwrite
#ifdef ONLINE_JUDGE
#define getchar Fread ::getchar
#define putchar Fwrite ::putchar
#endif
    struct Reader
    {
        template <typename T>
        Reader &operator>>(T &x)
        {
            char c = getchar();
            T f = 1;
            while (c < '0' || c > '9')
            {
                if (c == '-')
                    f = -1;
                c = getchar();
            }
            x = 0;
            while (c >= '0' && c <= '9')
            {
                x = x * 10 + (c - '0');
                c = getchar();
            }
            x *= f;
            return *this;
        }
        Reader() {}
    } cin;
    const char endl = '\n';
    struct Writer
    {
        template <typename T>
        Writer &operator<<(T x)
        {
            if (x == 0)
            {
                putchar('0');
                return *this;
            }
            if (x < 0)
            {
                putchar('-');
                x = -x;
            }
            static int sta[111];
            int top = 0;
            while (x)
            {
                sta[++top] = x % 10;
                x /= 10;
            }
            while (top)
            {
                putchar(sta[top] + '0');
                --top;
            }
            return *this;
        }
        Writer &operator<<(char c)
        {
            putchar(c);
            return *this;
        }
        Writer &operator<<(char *str)
        {
            int cur = 0;
            while (str[cur])
                putchar(str[cur++]);
            return *this;
        }
        Writer &operator<<(const char *str)
        {
            int cur = 0;
            while (str[cur])
                putchar(str[cur++]);
            return *this;
        }
        Writer() {}
    } cout;
#define cin Fastio ::cin
#define cout Fastio ::cout
#define endl Fastio ::endl
} // namespace Fastio

int T, n, p;

int ans;

signed main()
{
    cin >> T;
    while (T--)
    {
        ans = 0;
        cin >> n >> p;
        if (p == 1)
        {
            cout << 0 << endl;
            continue;
        }
        int k;
        while (n >= 1)
        {
            k = n / p;
            if (k * p <= n)
                k++;
            ans += n - k + 1;
            n = (k - 1) / p;
        }
        cout << ans << endl;
    }
}

T3 『JROI-3』1÷0

咕咕咕。。。

T4 『JROI-3』删树

比较有趣的一道题。

考场 C O D E CODE CODE (错解,没考虑完全,要是数据恶心点就被卡死了)

#include <bits/stdc++.h>
using namespace std;

#define int long long

inline int read()
{
    char c = getchar();
    int x = 0;
    for (; !isdigit(c); c = getchar())
        ;
    for (; isdigit(c); c = getchar())
        x = (x << 1) + (x << 3) + (c ^ 48);
    return x;
}

int n;

int kkk, kkkk, kkkkk;

int x;

int X[50005];

int mmax, op;

signed main()
{
    n = read();
    for (int i = 1; i <= n; ++i)
    {
        x = read();
        if (x == 1)
        {
            X[++kkk] = i;
        }
        if (x == 2)
            kkkk++;
        if (x != 1 && x != 2)
            kkkkk++;
        if (mmax < x)
        {
            mmax = x;
            op = i;
        }
    }
    if (kkk == 2 && kkk + kkkk == n)
    {
        cout << "dis " << X[1] << " " << X[2] << endl;
        cout.flush();
        x = read();
        cout << "! " << x << endl;
        cout.flush();
        return 0;
    }

    if (kkk == n - 1)
    {
        cout << "del\n";
        cout.flush();
        n = read();
        for (int i = 1; i <= n; ++i)
        {
            read();
        }
        cout << "! 0\n";
        cout.flush();
        return 0;
    }
    if (kkk == n - 2)
    {
        cout << "del\n";
        cout.flush();
        n = read();
        for (int i = 1; i <= n; ++i)
        {
            read();
        }
        cout << "dis 1 2\n";
        cout.flush();
        x = read();
        cout << "! " << x << endl;
        cout.flush();
        return 0;
    }

    if (n == 1)
    {
        cout << "! 0\n";
        cout.flush();
        return 0;
    }
    if (n == 2)
    {
        cout << "dis 1 2\n";
        cout.flush();
        x = read();
        cout << "! " << x << endl;
        cout.flush();
        return 0;
    }
    if (kkkkk == 1)
    {
        int ans = 0;
        if (kkk <= 140)
        {
            for (int i = 1; i <= kkk; ++i)
            {
                cout << "dis " << op << " " << X[i] << endl;
                cout.flush();
                x = read();
                ans += x;
            }
            cout << "! " << ans << endl;
            cout.flush();
            return 0;
        }
    }
    if (n > 2)
    {
        while (n > 2)
        {
            kkk = 0;
            kkkk = 0;
            kkkkk = 0;
            mmax = 0;
            op = 0;
            cout << "del" << endl;
            cout.flush();
            n = read();
            for (int i = 1; i <= n; ++i)
            {
                x = read();
                if (x == 1)
                {
                    X[++kkk] = i;
                }
                if (x == 2)
                    kkkk++;
                if (x != 1)
                    kkkkk++;
                if (mmax < x)
                {
                    mmax = x;
                    op = i;
                }
            }
            if (kkk == 2 && kkk + kkkk == n)
            {
                cout << "dis " << X[1] << " " << X[2] << endl;
                cout.flush();
                x = read();
                cout << "! " << x << endl;
                cout.flush();
                return 0;
            }
            if (kkk == n - 1)
            {
                cout << "del\n";
                cout.flush();
                n = read();
                for (int i = 1; i <= n; ++i)
                {
                    read();
                }
                cout << "! 0\n";
                cout.flush();
                return 0;
            }
            if (kkk == n - 2)
            {
                cout << "del\n";
                cout.flush();
                n = read();
                for (int i = 1; i <= n; ++i)
                {
                    read();
                }
                cout << "dis 1 2\n";
                cout.flush();
                x = read();
                cout << "! " << x << endl;
                cout.flush();
                return 0;
            }
            // if (kkkkk == 1)
            // {
            //     int ans = 0;
            //     for (int i = 1; i <= kkk; ++i)
            //     {
            //         cout << "dis " << op << " " << X[i] << endl;
            //         cout.flush();
            //         x = read();
            //         ans += x;
            //     }
            //     cout << "! " << ans << endl;
            //     cout.flush();
            //     return 0;
            // }
        }
        if (n <= 1)
        {
            cout << "! 0\n";
            cout.flush();
            return 0;
        }
        if (n == 2)
        {
            cout << "dis 1 2\n";
            cout.flush();
            x = read();
            cout << "! " << x << endl;
            cout.flush();
            return 0;
        }
    }
}

如果满足询问次数 2 ∗ k k k + p p p ≤ 142 2*kkk+ppp\leq 142 2kkk+ppp142,其中 k k k kkk kkk 为当前的叶子结点的个数, p p p ppp ppp 为之前询问了几次,就执行如下步骤:

  • 询问所有叶子结点的 dfs 序,并按照 dfs 序排序。
  • 询问第 i i i 个叶子和第 i + 1 i+1 i+1 个叶子的距离,特别的,定义第 k k k + 1 kkk+1 kkk+1 个叶子是第 1 1 1 个,然后将输入累加到 a n s ans ans
  • 输出 a n s / 2 ans/2 ans/2,因为所有边累加了两次。

如果不满足,就执行 del 操作,再重新计算叶子数量。

简短的 C O D E CODE CODE

#include <bits/stdc++.h>
using namespace std;

#define int long long

inline int read()
{
    char c = getchar();
    int x = 0;
    for (; !isdigit(c); c = getchar())
        ;
    for (; isdigit(c); c = getchar())
        x = (x << 1) + (x << 3) + (c ^ 48);
    return x;
}

int n;

int kkk;

int x;

int ppp;

int X[50005];

int dfn[50005];

bool cmp(int a, int b)
{
    return dfn[a] < dfn[b];
}

signed main()
{
    n = read();
    for (int i = 1; i <= n; ++i)
    {
        x = read();
        if (x == 1)
            X[++kkk] = i;
    }
    if (2 * kkk + ppp <= 140)
    {
        int ans = 0;
        for (int i = 1; i <= kkk; ++i)
        {
            cout << "dfn " << X[i] << endl;
            cout.flush();
            dfn[X[i]] = read();
        }
        sort(X + 1, X + kkk + 1, cmp);
        for (int i = 1; i <= kkk; ++i)
        {
            if (i == kkk)
            {
                cout << "dis " << X[1] << " " << X[kkk] << endl;
                cout.flush();
                x = read();
                ans += x;
            }
            else
            {
                cout << "dis " << X[i] << " " << X[i + 1] << endl;
                cout.flush();
                x = read();
                ans += x;
            }
        }
        cout << "! " << ans / 2 << endl;
        cout.flush();
        return 0;
    }
    else
    {
        while (n)
        {
            if (2 * kkk + ppp <= 140)
            {
                int ans = 0;
                for (int i = 1; i <= kkk; ++i)
                {
                    cout << "dfn " << X[i] << endl;
                    cout.flush();
                    dfn[X[i]] = read();
                }
                sort(X + 1, X + kkk + 1, cmp);
                for (int i = 1; i <= kkk; ++i)
                {
                    if (i == kkk)
                        cout << "dis " << X[1] << " " << X[kkk] << endl;
                    else
                        cout << "dis " << X[i] << " " << X[i + 1] << endl;
                    cout.flush();
                    x = read();
                    ans += x;
                }
                cout << "! " << ans / 2 << endl;
                cout.flush();
                return 0;
            }
            else
            {
                ppp++;
                kkk = 0;
                cout << "del" << endl;
                cout.flush();
                n = read();
                for (int i = 1; i <= n; ++i)
                {
                    x = read();
                    if (x == 1)
                        X[++kkk] = i;
                }
            }
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值