• 【ybt金牌导航6-4-2】【luogu P1903】数颜色 / 维护队列(带修莫队)


    数颜色 / 维护队列

    题目链接:ybt金牌导航6-4-2 / luogu P1903

    题目大意

    要你维护一个序列,可能会改变一个位置的数,还有询问一个区间内有多少种数。

    思路

    这道题有多种做法,然后我们考虑用带修莫队来做。

    莫队是两个指针第一个按块搞,第二个就按个搞。
    那我们带修的话我们就可以加上一个时间指针。

    那也是一个道理,我们就也是分成块,然后第一个排序按左边的块排,第二个排序按右边的块排,接着就按着时间排。
    然后就每次三个指针移动一下就可以了。

    然后至于时间指针的移动,把位置 (x)(a) 换成 (b),就相当于把 (a) 的贡献消除,加上 (b) 的贡献。

    然后就差不多了,我们最优会选取 (n^{frac{2}{3}}) 的长度,这样复杂度是 (n^{frac{5}{3}}) 的。、
    (搞这个长度直接用 ( ext{pow}) 函数)

    代码

    #include<cmath>
    #include<cstdio>
    #include<algorithm>
    
    using namespace std;
    
    struct node {
    	int t, x, y, num, ans;
    }a[140001];
    int n, m, x, y, block[140001], t, col[140001];
    int fr[140001], to[140001], lst[140001], sz;
    int q, tim, pl[140001], num[1000001], ans;
    bool in[140001];
    char op;
    
    bool cmp(node x, node y) {//莫队的排序
    	if (block[x.x] != block[y.x]) return block[x.x] < block[y.x];
    	if (block[x.y] != block[y.y]) return block[x.y] < block[y.y];
    	return x.t < y.t;
    }
    
    void clac(int p) {//更新当前位置的值
    	if (in[p]) {
    		num[col[p]]--;
    		if (!num[col[p]]) ans--;
    	}
    	else {
    		num[col[p]]++;
    		if (num[col[p]] == 1) ans++;
    	}
    	in[p] ^= 1;
    }
    
    void change(int p, int t) {//换数
    	if (in[p]) {
    		clac(p);
    		col[p] = t;
    		clac(p);
    	}
    	else col[p] = t;
    }
    
    bool cmp1(node x, node y) {
    	return x.num < y.num;
    }
    
    int main() {
    	scanf("%d %d", &n, &m);
    	for (int i = 1; i <= n; i++) {
    		scanf("%d", &lst[i]);
    		col[i] = lst[i];
    	}
    	
    	sz = pow(n, 2.0 / 3);
    	for (int i = 1; i <= n; i++)
    		block[i] = (i - 1) / sz + 1;
    	
    	for (int i = 1; i <= m; i++) {
    		op = getchar();
    		while (op != 'Q' && op != 'R') op = getchar();
    		
    		if (op == 'Q') {
    			scanf("%d %d", &x, &y);
    			a[++q] = (node){tim, x, y, i, 0};
    		}
    		else {
    			scanf("%d %d", &x, &y);
    			pl[++tim] = x;
    			fr[tim] = lst[x];
    			to[tim] = y;
    			lst[x] = y;
    		}
    	}
    	
    	sort(a + 1, a + q + 1, cmp);
    	t = 0; x = 1; y = 0;
    	for (int i = 1; i <= q; i++) {
    		while (t < a[i].t) t++, change(pl[t], to[t]);//三个指针分别移动
    		while (t > a[i].t) change(pl[t], fr[t]), t--;
    		while (x < a[i].x) clac(x), x++;
    		while (x > a[i].x) x--, clac(x);
    		while (y < a[i].y) y++, clac(y);
    		while (y > a[i].y) clac(y), y--;
    		a[i].ans = ans;
    	}
    	
    	sort(a + 1, a + q + 1, cmp1);
    	for (int i = 1; i <= q; i++) printf("%d
    ", a[i].ans);
    	
    	return 0;
    }
    
  • 相关阅读:
    python_workone
    python___"TypeError: 'module' object is not callable"
    显示pycharm的行号
    pycharm切换python版本
    yum安装pip
    informix数据库常用命令(转)
    eclipse打不开的解决办法
    linux修改时间大全
    在安装mysqli的时候,出现error: ext/mysqlnd/mysql_float_to_double.h: No such file or directory
    Amazon Linux AMI 2015.09 (HVM)平台搭建lamp
  • 原文地址:https://www.cnblogs.com/Sakura-TJH/p/YBT_JPDH_6-4-2.html
Copyright © 2020-2023  润新知