ABC339

基本情况

ABC秒了,D读错题卡了一段时间,还好爆搜强项,E感觉极其类似LIS,但是似乎又不能用二分DP来写。

E

https://atcoder.jp/contests/abc339/tasks/abc339_e

线段树优化DP

事实如此,确实类似LIS,但是通过线段树来维护区间最大值.

暂时还没有熟练线段树,先用atc的库来平替.

实现上就是将元素依次加入线段树 , 然后用当前元素符合条件区间的最大值来更新当前元素对应点的值.

最后输出总区间最大值即可.

换言之,对于当前的 \(dp_i\),只能从\(dp_j(j < i \and \left | a_i - a_j \right | \leq k)\) 中找最大。

所以对线段树中对应的 \(a_i\) 这个点更新最大步数,然后转移时找数值在 \([a_i - d, a_i + d]\) 中对应的DP最大值就好。

int op(int a, int b) { return max(a, b); }
int e() { return 0; }
const int A = 500010;

int main()
{
	int n, d;
	cin >> n >> d;
	atcoder::segtree<int, op, e> seg(A);
	for (int i = 0, x; i < n; i++) {
		cin >> x;
		int l = max(0, x - d);
		int r = min(A - 1, x + d);
		int MAX = seg.prod(l, r + 1);
		seg.set(x, MAX + 1);
	}
	cout << seg.all_prod() << endl;
	return 0;
}

F - Product Equality

https://atcoder.jp/contests/abc339/tasks/abc339_f

哈希人类智慧

怎么验证三个极大数 \(A_i\times A_j = A_k\)

直接类比哈希,找几个模数作同余,只要在所有模数意义下相等那就可以认为是相等。

一开始还卡在两个大的数要怎么进行乘法,想到从数位上考虑去了。

事实上可以直接在输入时取模,比如 \(14432\) 其实就是 \(1\times 10^4 + 4\times10^3 + 4\times 10^2 + 3\times10^1 + 2\times10^0\)

因此在输入一个极大数的时候就可以边乘底数边取模,然后构造同余意义下的较小数。

换一种角度,实际上就是把数字当成字符串了,每个数位是字符串的字符,那么处理就是很自然的了。

在同余意义下进行相乘验证即可。

constexpr int B = 3;
int mod[]{1000000007, 1000000009, 998244353};
int base[]{10, 10, 10};

struct String {
    std::vector<i64> hash[B];
    std::string s;
    String(){}
    String(std::string s_) : s(s_) {
        for (int i = 0; i < B; i++) {
            hash[i].push_back(0);
            for (auto& ch : s) {
                hash[i].push_back((hash[i].back() * base[i] + (ch - '0')) % mod[i]);//其实就是正常的哈希处理
            }
        }
    }   

    friend std::istream &operator>>(std::istream &is, String& str) {
        is >> str.s;
        str = String(str.s);
        return is;
    }

    std::array<i64, B> get() {std::array<i64, B> res{}; for (int i = 0; i < B; i++) {res[i] = hash[i].back();} return res;}

};

std::array<i64, B> multiply(String& a, String& b) {
    std::array<i64, B> res{}; for (int i = 0; i < B; i++) {res[i] = a.hash[i].back() * b.hash[i].back() % mod[i];} return res;
}


signed main() {

    std::cin.tie(nullptr)->sync_with_stdio(false);

    int n;
    std::cin >> n;
    std::map<std::array<i64, B>, int> cnt;
    std::vector<String> s(n);
    for (i64 i = 0; i < n; i++) {
        std::cin >> s[i];
        cnt[s[i].get()] += 1;
    }

    i64 ans = 0;

    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            std::array<i64, B> mul = multiply(s[i], s[j]);
            ans += cnt[mul];
        }
    }

    std::cout << ans << '\n';

    return 0;
}
posted @ 2024-02-03 22:54  加固文明幻景  阅读(38)  评论(0编辑  收藏  举报