zoukankan      html  css  js  c++  java
  • bzoj5016 & loj2254 [Snoi2017]一个简单的询问 莫队

    题目传送门

    https://lydsy.com/JudgeOnline/problem.php?id=5016

    https://loj.ac/problem/2254

    题解

    原式是这样的

    [sum_{x = 0}^{infty} get(l_1, r_1, x) cdot get(l_2, r_2, x) ]

    因为一次询问需要用到两个区间,本来按理说最擅长两个区间的查询的主席树,这里也没有办法建立。

    然后分块或者莫队的话也无能为力。

    于是我们考虑对询问本身做一些修改,使得一次询问只涉及两个参数。


    [sum_{x = 0}^{infty} get(l_1, r_1, x) cdot get(l_2, r_2, x)\= sum_{x=0}^{infty} get(1, r_1, x) cdot get(1, r_2, x) - get(1, l1 - 1, x) cdot get(1, r2, x) - get(1, l2 - 1, x) cdot get(1, r1, x) + get(1, l1 - 1, x) cdot get(1, l2 - 1, x) ]

    这样,我们令 (g(a, b)) 表示 (sumlimits_{x = 0}^{infty} get(1, a, x) cdot get(1, b, x)),那么我们就把上面的一个询问分解成了 (4) 个询问。

    然后 (g(a, b)) 可以对 (a, b) 进行莫队完成。


    时间复杂度 (O(nsqrt{4m}))。这样写复杂度似乎不是很标准,因为复杂度里面不应该有任何常数。

    #include<bits/stdc++.h>
    
    #define fec(i, x, y) (int i = head[x], y = g[i].to; i; i = g[i].ne, y = g[i].to)
    #define dbg(...) fprintf(stderr, __VA_ARGS__)
    #define File(x) freopen(#x".in", "r", stdin), freopen(#x".out", "w", stdout)
    #define fi first
    #define se second
    #define pb push_back
    
    template<typename A, typename B> inline char smax(A &a, const B &b) {return a < b ? a = b, 1 : 0;}
    template<typename A, typename B> inline char smin(A &a, const B &b) {return b < a ? a = b, 1 : 0;}
    
    typedef long long ll; typedef unsigned long long ull; typedef std::pair<int, int> pii;
    
    template<typename I> inline void read(I &x) {
    	int f = 0, c;
    	while (!isdigit(c = getchar())) c == '-' ? f = 1 : 0;
    	x = c & 15;
    	while (isdigit(c = getchar())) x = (x << 1) + (x << 3) + (c & 15);
    	f ? x = -x : 0;
    }
    
    const int N = 50000 + 7;
    
    #define bl(x) (((x) - 1) / blo + 1)
    
    int n, m, blo, Q;
    ll val;
    int a[N], cl[N], cr[N];
    ll ans[N];
    
    struct Query {
    	int opt, l, r;
    	ll *ans;
    	inline Query() {}
    	inline Query(const int &opt, const int &l, const int &r, ll *ans) : opt(opt), l(l), r(r), ans(ans) {
    		if (l > r) std::swap(this->l, this->r);
    	}
    	inline bool operator < (const Query &b) const { return bl(l) != bl(b.l) ? l < b.l : r < b.r; }
    } q[N << 2];
    
    inline void addl(int x) {
    	val += cr[a[x]];
    	++cl[a[x]];
    }
    inline void addr(int x) {
    	val += cl[a[x]];
    	++cr[a[x]];
    }
    inline void dell(int x) {
    	val -= cr[a[x]];
    	--cl[a[x]];
    }
    inline void delr(int x) {
    	val -= cl[a[x]];
    	--cr[a[x]];
    }
    
    inline void work() {
    	blo = sqrt(Q);
    	std::sort(q + 1, q + Q + 1);
    	int l = 0, r = 0;
    	for (int i = 1; i <= Q; ++i) {
    		while (r < q[i].r) addr(++r);
    		while (l < q[i].l) addl(++l);
    		while (l > q[i].l) dell(l--);
    		while (r > q[i].r) delr(r--);
    		*q[i].ans += q[i].opt * val;
    	}
    	for (int i = 1; i <= m; ++i) printf("%lld
    ", ans[i]);
    }
    
    inline void init() {
    	read(n);
    	for (int i = 1; i <= n; ++i) read(a[i]);
    	read(m);
    	for (int i = 1; i <= m; ++i) {
    		int l1, r1, l2, r2;
    		read(l1), read(r1), read(l2), read(r2);
    		q[++Q] = Query(1, r1, r2, ans + i);
    		if (l2 > 1) q[++Q] = Query(-1, l2 - 1, r1, ans + i);
    		if (l1 > 1) q[++Q] = Query(-1, l1 - 1, r2, ans + i);
    		if (l1 > 1 && l2 > 1) q[++Q] = Query(1, l1 - 1, l2 - 1, ans + i);
    	}
    }
    
    int main() {
    #ifdef hzhkk
    	freopen("hkk.in", "r", stdin);
    #endif
    	init();
    	work();
    	fclose(stdin), fclose(stdout);
    	return 0;
    }
    
  • 相关阅读:
    Eclipse复制或修改项目后,把项目部署后发现还是原来的项目名称
    eclipse设置新建jsp文件默认字符编码为utf-8
    mysql数据库无法插入中文字符
    Dos中查看mysql数据时 中文乱码
    spring 解决中文乱码问题
    mysql再次安装问题
    The import javax.servlet cannot be resolved
    eclipse快捷键补全
    eclipse自动补全
    hibernate运行常见错误
  • 原文地址:https://www.cnblogs.com/hankeke/p/bzoj5016.html
Copyright © 2011-2022 走看看