AtCoder Beginner Contest 339

AtCoder Beginner Contest 339

A - TLD

签到

B - Langton's Takahashi

发现步数和网格范围都不大,直接模拟即可

C - Perfect Bus

题目的合法性在于不能为负数,那么初始人数就有了二分性。

二分的找出初始的最小人数,然后跑一边即可

#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define Acode ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define int long long
const int N = 4e6 + 10;
int n;
int a[N];

bool check(int mid)
{
    int x = mid;
    for (int i = 1; i <= n; i++)
    {
        x = x + a[i];
        if (x < 0)
            return false;
    }
    return true;
}

void solve()
{
    cin >> n;
    for (int i = 1; i <= n; i++)
    {
        cin >> a[i];
    }
    int l = 0, r = 1e15;
    while (l <= r)
    {
        int mid = l + r >> 1;
        if (check(mid))
            r = mid - 1;
        else
            l = mid + 1;
    }
    int x = l;
    for (int i = 1; i <= n; i++)
    {
        x = x + a[i];
    }
    cout << x << endl;
}

signed main()
{
    Acode;
    int T = 1;
    // cin >> T;
    while (T--)
    {
        solve();
    }
    return 0;
}

D - Synchronized Players

BFS的练习题,发现60的数据范围支持n^4的暴搜,所以我们就可以有x1,y1,x2,y2的状态来搜索,由于bfs队列内的不减性质,所以率先重合的次数就是答案

#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define Acode ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define int long long
const int N = 110;
int n;
char mp[N][N];
int mpp[72][72][72][72];
int a[N];
int dir[4][2] = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}};
int vis[N][N];
// woc TLE
struct node
{
    int x1, y1;
    int x2, y2;
};
// map<array<int, 4>, int> mpp;
int xx1, xx2, yy1, yy2;
int ans = -1;

void bfs1()
{
    queue<pair<int, int>> q;
    q.push({xx1, yy1});
    vis[xx1][yy1] = 1;
    while (q.size())
    {
        int x = q.front().first;
        int y = q.front().second;
        q.pop();
        for (int i = 0; i < 4; i++)
        {
            int dx = x + dir[i][0];
            int dy = y + dir[i][1];
            if (dx < 1 || dx > n || dy < 1 || dy > n)
                continue;
            if (!vis[dx][dy])
            {
                vis[dx][dy] = 1;
                q.push({dx, dy});
            }
        }
    }
}

void bfs()
{
    memset(mpp, 0x3f, sizeof mpp);
    mpp[xx1][yy1][xx2][yy2] = 0;
    // mpp[{xx1, yy1, xx2, yy2}] = 0;
    // 特判-1 试一下算了
    queue<node> q;
    q.push({xx1, yy1, xx2, yy2});
    while (q.size())
    {
        auto it = q.front();
        q.pop();
        int x1 = it.x1;
        int y1 = it.y1;
        int x2 = it.x2;
        int y2 = it.y2;
        for (int i = 0; i < 4; i++)
        {
            int dx1 = x1 + dir[i][0];
            int dy1 = y1 + dir[i][1];
            int dx2 = x2 + dir[i][0];
            int dy2 = y2 + dir[i][1];
            if (mp[dx1][dy1] == '#' || dx1 <= 0 || dx1 > n || dy1 <= 0 || dy1 > n)
            {
                dx1 = x1;
                dy1 = y1;
            }
            if (mp[dx2][dy2] == '#' || dx2 <= 0 || dx2 > n || dy2 <= 0 || dy2 > n)
            {
                dx2 = x2;
                dy2 = y2;
            }
            // mpp[dx1][dy1][dx2][dy2]
            // mpp[x1][y1][x2][y2]
            if (mpp[dx1][dy1][dx2][dy2] > mpp[x1][y1][x2][y2] + 1)
            {
                mpp[dx1][dy1][dx2][dy2] = mpp[x1][y1][x2][y2] + 1;
                q.push({dx1, dy1, dx2, dy2});
            }
            if (dx1 == dx2 && dy1 == dy2)
            {
                ans = mpp[dx1][dy1][dx2][dy2];
                return;
            }
        }
    }
}
void solve()
{
    cin >> n;
    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= n; j++)
        {
            cin >> mp[i][j];
            if (mp[i][j] == 'P')
            {
                if (xx1 == 0)
                {
                    xx1 = i;
                    yy1 = j;
                }
                else
                {
                    xx2 = i;
                    yy2 = j;
                }
            }
        }
    }
    bfs1();
    if (vis[xx2][yy2] == 0)
    {
        cout << -1 << endl;
        return;
    }
    bfs();
    cout << ans << endl;
}

signed main()
{
    Acode;
    int T = 1;
    // cin >> T;
    while (T--)
    {
        solve();
    }
    return 0;
}

E - Smooth Subsequence

非常经典的dp,dp[i]的含义为选了第i个数,并且以它结尾的子序列的最长的长度,和LIS非常像。

那么这么想的话,我们是n^2的dp,不能通过。 观察发现就是每次就是从一个范围内,从其中的最大值来转移,所以可以用线段树来优化dp,开的类似与值域线段树,只关系值不关心它的位置。从这个值域内挑一个最大值来转移。

#include <bits/stdc++.h>
using namespace std;
#define Acode ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define int long long
#define endl '\n'
const int N = 1e6 + 10;
int a[N];
int dp[N];
// 先写n方的dp转移

struct info
{
    int mav;
};

struct node
{
    info val;
} seg[N << 2];

info operator+(const info &a, const info &b)
{
    info c;
    c.mav = max(a.mav, b.mav);
    return c;
}

void up(int id)
{
    seg[id].val = seg[id << 1].val + seg[id << 1 | 1].val;
}

// void build(int id, int l, int r) // id代表区间节点标号,l,r代表该区间节点的左右端点
// {
//     if (l == r)
//     {
//         seg[id].val = {a[l], 1};
//         return;
//     }
//     int mid = l + r >> 1;
//     build(id << 1, l, mid);
//     build(id << 1 | 1, mid + 1, r);
//     up(id);
// }

void change(int id, int l, int r, int x, int val)
{
    if (l == r)
    {
        seg[id].val = {val};
        return;
    }
    int mid = l + r >> 1;
    if (x <= mid)
        change(id << 1, l, mid, x, val);
    else
        change(id << 1 | 1, mid + 1, r, x, val);
    up(id);
}

info query(int id, int l, int r, int ql, int qr)
{
    if (ql <= l && r <= qr)
        return seg[id].val;
    int mid = l + r >> 1;
    if (qr <= mid) // 同理,查询区间属于左儿子就向左边去找 ,反之是右儿子
        return query(id << 1, l, mid, ql, qr);
    else if (ql > mid)
        return query(id << 1 | 1, mid + 1, r, ql, qr);
    else
        return query(id << 1, l, mid, ql, qr) + query(id << 1 | 1, mid + 1, r, ql, qr);
}

void solve()
{
    int n, d;
    cin >> n >> d;
    for (int i = 1; i <= n; i++)
        cin >> a[i];
    for (int i = 1; i <= n; i++)
    {
        auto w = query(1, 1, N, max(1LL, a[i] - d), min(N, a[i] + d));
        int t = w.mav;
        dp[i] = max(dp[i], t + 1);
        auto it = query(1, 1, N, a[i], a[i]);
        int x = it.mav;
        if (x < dp[i])
        {
            change(1, 1, N, a[i], dp[i]);
        }
    }
    int ans = 0;
    for (int i = 1; i <= n; i++)
    {
        // cerr << dp[i] << " ";
        ans = max(ans, dp[i]);
    }
    cout << ans << endl;
}

signed main()
{
    Acode;
    int T = 1;
    // cin >> T;
    while (T--)
    {
        solve();
    }
    return 0;
}

F - Product Equality

赛时没思路,晚上补

G - Smaller Sum

数据结构,晚上补

posted @ 2024-02-06 20:28  ヤ﹎句号悠灬  阅读(27)  评论(0)    收藏  举报