ABC339

D

在一个N*N的平面中有一些墙,还放置了两个棋子
每次操作只能将两个棋子同时上下左右移动,如果棋子被墙挡住就不能动
问最少需要几步能将两个棋子走到一起


bfs

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <string>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <map>
#include <set>
#include <vector>
#include <queue>
#include <stack>
#include <unordered_map>
#include <algorithm>

using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef vector<int> vi;


int n;
char s[70][70];

struct Item {
    int r0, c0, r1, c1;
};
int f[61][61][61][61];

int dir[4][2] = {
    {0, 1}, {-1, 0}, {0, -1}, {1, 0}
};


int main(){
    //freopen("in.txt", "r", stdin);
    cin >> n;
    for (int i = 0; i < 70; ++i) {
        for (int j = 0; j < 70; ++j) {
            s[i][j] = '#';
        }
    }
    vector<pii> temp;
    for (int i = 1; i <= n; ++i) {
        string t;
        cin >> t;
        for (int j = 1; j <= n; ++j) {
            s[i][j] = t[j - 1];
            if (s[i][j] == 'P') {
                temp.push_back({ i, j });
            }
        }
    }
    memset(f, 0x3f, sizeof(f));
    queue<Item> qu;
    auto [r0, c0] = temp[0];
    auto [r1, c1] = temp[1];
    if (r0 > r1) {
        swap(r0, r1);
        swap(c0, c1);
    }
    qu.push(Item{ r0, c0, r1, c1 });
    f[r0][c0][r1][c1] = 0;
    int ans = -1;
    while (qu.size()) {
        auto [r0, c0, r1, c1] = qu.front();
        qu.pop();
        if (r0 == r1 && c0 == c1) {
            ans = f[r0][c0][r1][c1];
            break;
        }
        for (auto d : dir) {
            int nr0 = r0 + d[0], nc0 = c0 + d[1];
            int nr1 = r1 + d[0], nc1 = c1 + d[1];
            if (s[nr0][nc0] == '#') {
                nr0 = r0, nc0 = c0;
            }
            if (s[nr1][nc1] == '#') {
                nr1 = r1, nc1 = c1;
            }
            if (nr0 > nr1) {
                swap(nr0, nr1);
                swap(nc0, nc1);
            }
            int val = f[r0][c0][r1][c1] + 1;
            if (f[nr0][nc0][nr1][nc1] > val) {
                f[nr0][nc0][nr1][nc1] = val;
                qu.push(Item({ nr0, nc0, nr1, nc1 }));
            }
        }
    }
    printf("%d\n", ans);
    return 0;
}

E

给定一个数列 A A A
获取长度最长的子序列,其中相邻两项的差绝对值不得大于d


这个题有 A i < = 500000 A_i<=500000 Ai<=500000的限制,所以好做一点,直接上线段树
对于每个 A i A_i Ai,求 A i − d A_i-d Aid A i + d A_i+d Ai+d范围内的最大答案再加1
如果没有数据限制,问题规模也不是特别大,把 A i , A i − d , A i + d A_i,A_i-d,A_i+d Ai,Aid,Ai+d这些点离散化就可以了。

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <string>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <map>
#include <set>
#include <vector>
#include <queue>
#include <stack>
#include <unordered_map>
#include <algorithm>

using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef vector<int> vi;

#define lu (u * 2)
#define ru (u * 2 + 1)
const int N = 500005;
int a[N];
int f[N];
int n, d;

struct SegTree {
    struct Node {
        int l, r, mx;
    } tr[N << 2];

    void up(int u) {
        tr[u].mx = max(tr[lu].mx, tr[ru].mx);
    }

public:
    void build(int l, int r, int u) {
        tr[u] = { l, r, 0 };
        if (l == r)
            return;
        int mi = (l + r) / 2;
        build(l, mi, lu);
        build(mi + 1, r, ru);
    }

    void update(int pos, int u, int val) {
        if (tr[u].l == tr[u].r) {
            tr[u].mx = val;
            return;
        }
        int mi = (tr[u].l + tr[u].r) / 2;
        if (pos <= mi)
            update(pos, lu, val);
        else
            update(pos, ru, val);
        up(u);
    }

    int query(int l, int r, int u) {
        if (l <= tr[u].l && tr[u].r <= r) {
            return tr[u].mx;
        }
        int mi = (tr[u].l + tr[u].r) / 2;
        int rt = 0;
        if (l <= mi) {
            rt = max(rt, query(l, r, lu));
        }
        if (r > mi) {
            rt = max(rt, query(l, r, ru));
        }
        return rt;
    }
} st;


int main(){
    //freopen("in.txt", "r", stdin);
    cin >> n >> d;
    st.build(1, 500000, 1);
    int ans = 0;
    for (int i = 1; i <= n; ++i) {
        cin >> a[i];
        int l = max(1, a[i] - d), r = min(500000, a[i] + d);
        f[i] = st.query(l, r, 1) + 1;
        st.update(a[i], 1, f[i]);
        ans = max(ans, f[i]);
    }
    printf("%d\n", ans);
    return 0;
}

F

N个超级大数 A i < 1 0 1000 A_i<10^{1000} Ai<101000
A i ∗ A k = A j A_i*A_k=A_j AiAk=Aj的tuple数


随机化题,思路是bloom filter的方法,知道这个方法就不难
如果两个大质数还是wa,那就再来一个filter

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <string>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <map>
#include <set>
#include <vector>
#include <queue>
#include <stack>
#include <unordered_map>
#include <algorithm>

using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef vector<int> vi;

int n;
ll a[1001], b[1001];
ll p0 = 10000019;
ll p1 = 99999989;
map<pll, int> h;


int main() {
    //freopen("in.txt", "r", stdin);
    cin >> n;
    for (int i = 1; i <= n; ++i) {
        string s;
        cin >> s;
        int m = s.length();
        ll t = 0;
        for (int j = 0; j < m; ++j) {
            t = t * 10 + s[j] - '0';
            t %= p0;
        }
        a[i] = t;
        t = 0;
        for (int j = 0; j < m; ++j) {
            t = t * 10 + s[j] - '0';
            t %= p1;
        }
        b[i] = t;
        h[{a[i], b[i]}] ++;
    }
    int ans = 0;
    for (int i = 1; i <= n; ++i) {
        for (int j = 1; j <= n; ++j) {
            ll v0 = a[i] * a[j] % p0, v1 = b[i] * b[j] % p1;
            if (h.count({ v0, v1 })) {
                ans += h[{v0, v1}];
            }
        }
    }
    printf("%d\n", ans);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值