• 带修改的莫队


    带修改的莫队

    【数颜色】

    墨墨购买了一套N支彩色画笔(其中有些颜色可能相同),摆成一排,你需要回答墨墨的提问。墨墨会向你发布如下指令:

    1、 Q L R代表询问你从第L支画笔到第R支画笔中共有几种不同颜色的画笔。

    2、 R P Col 把第P支画笔替换为颜色Col。

    为了满足墨墨的要求,你知道你需要干什么了吗?

    就是在基础的莫队上增加了修改操作

    所以需要挪动三个指针 (L) , (R) , (t)

    有个小技巧

    while (t < qt) {
        t++;
        if (ql <= m[t].pos and m[t].pos <= qr) {
            del(A[m[t].pos]);
            add(m[t].val);
        }
        swap(A[m[t].pos], m[t].val);
    }
    while (t > qt) {
        if (ql <= m[t].pos and m[t].pos <= qr) {
            del(A[m[t].pos]);
            add(m[t].val);
        }
        swap(A[m[t].pos], m[t].val);
        t--;
    }
    

    这个 (swap) 操作就很灵性

    块大小为 (^3sqrt {nt}) 的时候达到理论最快复杂度, 然而我 (TLE) 了 wrnm

    我这份代码 len = cbrt(1.0 * n * mcnt) + 1; 会被卡一个点

    前两个块大小 (n ^ {frac 2 3})(n^{frac 3 4}) 都可以通过, 0.75跑的最快。

    改成第三份理论最优就 TLE ? 难道又是我的毒瘤代码的锅

    //len = pow(n ,0.6667);
    len = pow(n, 0.75);
    //len = pow(n * mcnt, 0.333) + 1;
    
    /*
     * @Author: zhl
     * @Date: 2020-11-19 10:39:02
     */
    #include<bits/stdc++.h>
    using namespace std;
    
    const int N = 150000;
    int A[N], cnt[1000010], block[N];
    int n, mm, len;
    struct query {
    	int id, l, r, t;
    	bool operator < (const query& rhs)const {
    		int al = block[l], bl = block[rhs.l];
    		int ar = block[r], br = block[rhs.r];
    		if (al != bl)return al < bl;
    		if (ar != br)return ar < br;
    		return t < rhs.t;
    	}
    }q[N];
    struct modify {
    	int pos, val;
    }m[N];
    long long qcnt, mcnt, ans[N], now;
    
    void del(int x) {
    	if (!--cnt[x])now--;
    }
    void add(int x) {
    	if (!cnt[x]++)now++;
    }
    signed main() {
    	scanf("%d%d", &n, &mm);
    	for (int i = 1; i <= n; i++)scanf("%d", A + i);
    
    	while (mm--) {
    		char op[2]; int a, b;
    		scanf("%s%d%d", op, &a, &b);
    		if (*op == 'Q') {
    			qcnt++;
    			q[qcnt] = { qcnt,a,b, mcnt };
    			//q[qcnt] = { ++qcnt,a,b,mcnt };
    		}
    		else {
    			m[++mcnt] = { a,b };
    		}
    	}
    	len = pow(n ,0.6667);
    	for (int i = 1; i <= n; i++)block[i] = i / len;
    	sort(q + 1, q + 1 + qcnt);
    	int l = 1, r = 0, t = 0;
    
    	for (int i = 1; i <= qcnt; i++) {
    		int ql = q[i].l, qr = q[i].r, qt = q[i].t;
    		while (l < ql) del(A[l++]);
    		while (l > ql) add(A[--l]);
    		while (r < qr) add(A[++r]);
    		while (r > qr) del(A[r--]);
    
    		while (t < qt) {
    			t++;
    			if (ql <= m[t].pos and m[t].pos <= qr) {
    				del(A[m[t].pos]);
    				add(m[t].val);
    			}
    			swap(A[m[t].pos], m[t].val);
    		}
    		while (t > qt) {
    			if (ql <= m[t].pos and m[t].pos <= qr) {
    				del(A[m[t].pos]);
    				add(m[t].val);
    			}
    			swap(A[m[t].pos], m[t].val);
    			t--;
    		}
    		ans[q[i].id] = now;
    	}
    	for (int i = 1; i <= qcnt; i++)printf("%d
    ", ans[i]);
    }
    
  • 相关阅读:
    Java导出Excel(附完整源码)
    Scala语言学习笔记——方法、函数及异常
    python时间序列按频率生成日期
    socket主要函数介绍
    JAVA版CORBA程序
    Linux文件压缩命令笔记
    使用JAVA写一个简单的日历
    Node.js 文件系统
    Node.js 常用工具util
    Node.js 全局对象
  • 原文地址:https://www.cnblogs.com/sduwh/p/14008293.html
Copyright © 2020-2023  润新知