cf 1168 C. And Reachability

记录一些好题吧。
题意 就是问题你 数组上L R的两个位置 能不能抵达。。

这题可以逆向dp (应该也可以正向 。就是逻辑反过来 然后我们用R来找L。)
// 定义f[N][20],ne[20];
// f[i][j]就是i下标 j位能够抵达的最近的地方。。
// 然后到时候就可以用f[i][j]<=R 来判断成立。。
// ne[j] 就是最近的j位置是1 的下标位置。


#include <bits/stdc++.h>
using namespace std;
#define easy_code ios::sync_with_stdio(0), cin.tie(nullptr)
#define endl '\n'
#define int long long
#define ar array<int, 2>
#define arr array<int, 3>
int T, n, m, k, inf = 1e18;
int mod = 998244353; // 1e9+7;
const int N = 301314;
int f[N][20], ne[N];
signed main()
{
    easy_code;
#ifdef DEBUG
    freopen("../1.in", "r", stdin);
#endif
    cin >> n >> m;
    int a[n + 1];
    for (int i = 1; i <= n; ++i)
        cin >> a[i];
    memset(f, 0x3f, sizeof f);
    for (int i = n; i; i--)
    {
        for (int j = 0; j < 20; ++j)
            if (a[i] >> j & 1)
                f[i][j] = i;
            else
            {
                for (int k = 0; k < 20; ++k)
                    if (ne[k] != 0 && a[i] >> k & 1)
                        f[i][j] = min(f[i][j], f[ne[k]][j]);
                //这个是核心递推关系。
                // 有点像嫁接。。
                //就像我开的杂货店没有卖糖(j位置没有1)。。
                //(假如我们规定有卖同种货物的店之间是相通的) 
                //那我店里有盐k 我们就去最近的也有卖盐的店  问他最近的卖糖的店在哪里。
            }
        for (int j = 0; j < 20; ++j)
            if (a[i] >> j & 1)
                ne[j] = i;
    }
    while (m--)
    {
        int i, j;
        cin >> i >> j;
        bool ok = 0;
        for (int k = 0; k < 20; ++k)
            if ((a[j] >> k & 1) && f[i][k] <= j)
                ok = 1;
        cout << (ok ? "Shi" : "Fou") << endl;
    }
};

// 为啥继承ne[k]的位置 就能保证是最优解。。
// 我的理解是 因为逆向的每个下标位置 都会实时的更新f[i][j] 其中j的答案。。
// 而ne[k] 又是记录的最近的f[ne[k]][j]的答案。。
// 所以继承f[ne[k]][j] 就是j的最优解。。
// 。。。感觉还是有点绕。。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值