• [洛谷P3674]小清新人渣的本愿


    题目大意:给你$n$个数,$m$个询问($n,mleqslant 10^5$),有三种

    1.  $1;l;r;x$询问区间$[l,r]$内有没有两个数相减等于$x$
    2. $2;l;r;x$询问区间$[l,r]$内有没有两个数相加等于$x$
    3. $3;l;r;x$询问区间$[l,r]$内有没有两个数相乘等于$x$

    注意,两个数位置可以相同

    题解:莫队。

    1. 1. 即询问区间有没有一个数$s_i$,存在$s_i+x$
    2. 即询问区间有没有一个数$s_i$,存在$x-s_i$。$-s_i$不好考虑?存一个$N-s_i$不就好了?($N$为一个很大的数)
    3. 即询问区间有没有一个数$s_i|x$,存在$dfrac{x}{s_i}$

    这复杂度是$O(m(sqrt{n}+C))$($C=max{max{x_i},max{s_i}}$,题目中给的是$Cleqslant 10^5$)

    过不了?

    注意到操作一,好像像一个偏移,可以用$bitset$。

    那么操作二呢?

    $-s_i$不好考虑?存一个$N-s_i$不就好了?($N$为一个很大的数),也可以偏移耶。

    操作三?

    这个没有什么很好的方法,暴力枚举它的约数$s_i$,看是否存在$dfrac{n}{s_i}$,反正时间复杂度为$O(sqrt{x})$

    所以总复杂度为$O(m(sqrt{n}+dfrac{C}{64}))$

    卡点:



    C++ Code:

    #include <cstdio>
    #include <algorithm>
    #include <bitset>
    #include <cmath>
    #define bsz 317
    #define maxn 100010
    const int N = (1 << 17) - 1;
    std::bitset<N + 1> a, b, ans;
    int n, m; 
    int s[maxn], cnt[maxn];
    struct node {
    	int op, l, r, x, num;
    	inline bool operator < (const node &rhs) const {return (l / bsz == rhs.l / bsz) ? ((l / bsz + 1 & 1) ? (r < rhs.r) :(r > rhs.r)) : l < rhs.l;}
    } q[maxn];
    void work(int op, int x, int tg) {
    	if (op == 1) ans[tg] = (a & a >> x).any();
    	if (op == 2) ans[tg] = (a & b >> N - x).any();
    	if (op == 3) for (int i = sqrt(x); i; i--) if ((x % i == 0) && a[i] && a[x / i]) {ans.set(tg); break;}
    }
    int main() {
    	scanf("%d%d", &n, &m);
    	for (int i = 1; i <= n; i++) scanf("%d", &s[i]);
    	for (int i = 1; i <= m; i++) scanf("%d%d%d%d", &q[i].op, &q[i].l, &q[i].r, &q[i].x), q[i].num = i;
    	std::sort(q + 1, q + m + 1);
    	int l = 1, r = 1;
    	cnt[s[1]]++, a[s[1]] = b[N - s[1]] = true;
    	for (int i = 1; i <= m; i++) {
    		while (l > q[i].l) cnt[s[--l]]++ ? 0 : a[s[l]] = b[N - s[l]] = true;
    		while (r < q[i].r) cnt[s[++r]]++ ? 0 : a[s[r]] = b[N - s[r]] = true;
    		while (l < q[i].l) --cnt[s[l++]] ? 0 : a[s[l - 1]] = b[N - s[l - 1]] = false;
    		while (r > q[i].r) --cnt[s[r--]] ? 0 : a[s[r + 1]] = b[N - s[r + 1]] = false;
    		work(q[i].op, q[i].x, q[i].num);
    	}
    	for (int i = 1; i <= m; i++) puts(ans[i] ? "hana" : "bi");
    	return 0;
    }
    
  • 相关阅读:
    Android 监听键盘弹出/隐藏
    js 监听事件的叠加和移除
    如何用 Swift 语言构建一个自定控件
    适用于Web开发人员的20个CSS调色板
    学习Flutter应用开发有用的代码/库/专有技术列表
    学习Java的书籍资料
    可能对Flutter应用程序开发有用的代码/库/专有技术列表
    ios 动画:底部标签栏的概念设计
    iOS 开发者必不可少的 75 个工具
    创建Android Apps的30个经验教训
  • 原文地址:https://www.cnblogs.com/Memory-of-winter/p/9533602.html
Copyright © 2020-2023  润新知