• 【BZOJ 3809】Gty的二逼妹子序列


    这个莫队如果用线段树来维护的话,复杂度是$O(nsqrt{n}logn+qlogn)$

    很明显,可以看出来莫队每次$O(1)$的移动因为套上了线段树变成了$O(logn)$,但莫队移动的总数是非常大的,所以乘起来复杂度就上天了。

    那么有没有一种方法在修改上能够比线段树更快,同时又能相比暴力较快地回答询问呢?

    我们可以用分块,把序列分成$sqrt{n}$块,修改的复杂度是$O(1)$,回答询问的复杂度是$O(sqrt{n})$

    这样用分块代替线段树总复杂度就变成了$O(nsqrt{n}+qsqrt{n})$,然后就AC了~

    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int N = 100003;
    const int M = 1000003;
    void read(int &k) {
    	k = 0; int fh = 1; char c = getchar();
    	for(; c < '0' || c > '9'; c = getchar())
    		if (c == '-') fh = -1;
    	for(; c >= '0' && c <= '9'; c = getchar())
    		k = (k << 1) + (k << 3) + c - '0';
    	k = k * fh;
    }
    
    struct node {int l, r, a, b, id;} Q[M];
    int w[N], bel[N], n, m, sum[N], A[M], c[N];
    
    bool cmp(node A, node B) {return bel[A.l] == bel[B.l] ? A.r < B.r : A.l < B.l;}
    void update(int a, int flag) {
    	c[a] += flag;
    	if (flag == -1 && c[a] == 0) --sum[bel[a]];
    	if (flag == 1 && c[a] == 1) ++sum[bel[a]];
    }
    int QQ(int l, int r) {
    	int bl = bel[l], br = bel[r], ret = 0;
    	if (bl == br) {
    		for(int i = l; i <= r; ++i)
    			if (c[i] > 0) ++ret;
    		return ret;
    	}
    	for(int i = l; bel[i] == bel[l]; ++i)
    		if (c[i] > 0) ++ret;
    	for(int i = r; bel[i] == bel[r]; --i)
    		if (c[i] > 0) ++ret;
    	for(int i = bel[l] + 1; i < bel[r]; ++i)
    		ret += sum[i];
    	return ret;
    }
    
    int main() {
    	read(n); read(m);
    	for(int i = 1; i <= n; ++i) read(w[i]);
    	for(int i = 1; i <= m; ++i) {read(Q[i].l); read(Q[i].r); read(Q[i].a); read(Q[i].b); Q[i].id = i;}
    	
    	int t = sqrt(n + 0.5), cnt = 1, tmp = 1;
    	for(int i = 1; i <= n; ++i) {
    		bel[i] = tmp;
    		++cnt; if (cnt > t) {cnt = 1; ++tmp;}
    	}
    	
    	sort(Q + 1, Q + m + 1, cmp);
    	
    	int l = 1, r = 0, tol, tor;
    	for(int i = 1; i <= m; ++i) {
    		tol = Q[i].l; tor = Q[i].r;
    		while (l < tol) update(w[l++], -1);
    		while (l > tol) update(w[--l], 1);
    		while (r < tor) update(w[++r], 1);
    		while (r > tor) update(w[r--], -1);
    		A[Q[i].id] = QQ(Q[i].a, Q[i].b);
    	}
    	
    	for(int i = 1; i <= m; ++i) printf("%d
    ", A[i]);
    	
    	return 0;
    }
    

    分块大法好

  • 相关阅读:
    Headless MSBuild Support for SSDT (*.sqlproj) Projects
    dbDacFx Provider for Incremental Database publishing
    Cannot spawn... TortoisePlink
    Windows server 2012同时进行多个会话登陆的策略设置
    Workspace Cloning / Sharing in Jenkins
    How to change Jenkins default folder on Windows?
    使用Jenkins配置自动化构建
    Auto push git tag
    Azure Deploy
    sql server中index的REBUILD和REORGANIZE
  • 原文地址:https://www.cnblogs.com/abclzr/p/5477850.html
Copyright © 2020-2023  润新知