Bzoj2120/洛谷P1903 数颜色(莫队)

题面

Bzoj

洛谷

题解

考虑对操作离线后分块处理询问操作(莫队算法),将询问操作按照编号分块后左端点第一关键字,右端点第二关键字排序(分块大小为\(n^{\frac 23}\)),对于每一个询问操作,记下当前最后一个修改操作。

之后就是莫队的板子了。

#include <set>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <algorithm>
using std::min; using std::max;
using std::swap; using std::sort;
typedef long long ll;
using std::set;

template<typename T>
void read(T &x) {
    int flag = 1; x = 0; char ch = getchar();
    while(ch < '0' || ch > '9') { if(ch == '-') flag = -flag; ch = getchar(); }
    while(ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar(); x *= flag;
}

const int N = 2e6 + 10, M = 5e4 + 10;
int n, m, siz, col[M], l, r, tot[N], ans[M], ret, now, bel[M];
struct Ques { int x, y, z, pre; } q[M]; int cntqu;
struct Modi { int pos, val; } o[M]; int cntmo;
inline bool cmp (const Ques &a, const Ques &b) {
    if(bel[a.z] != bel[b.z]) return bel[a.z] < bel[b.z];
    if(a.x != b.x) return a.x < b.x;
    if(a.y != b.y) return a.y < b.y;
    return a.pre < b.pre;
}

inline void del (int c) { if(--tot[c] == 0) --ret; }
inline void add (int c) { if(++tot[c] == 1) ++ret; }
inline void doit (int now, int k) {
    if(o[now].pos >= q[k].x && o[now].pos <= q[k].y)
        del(col[o[now].pos]), add(o[now].val);
    swap(col[o[now].pos], o[now].val);
    //将操作记忆化,当处理替换时,相当于换过去,撤销时,相当于换回来。
}

int main () {
    read(n), read(m), siz = pow(n, 0.66666666);
    for(int i = 1; i <= n; ++i)
        read(col[i]), bel[i] = (i - 1) / siz + 1;
    char opt;
    while(m--) {
        scanf("\n%c", &opt);
        if(opt == 'Q') {
            read(q[++cntqu].x), read(q[cntqu].y);
            q[cntqu].z = cntqu, q[cntqu].pre = cntmo;
        } else read(o[++cntmo].pos), read(o[cntmo].val); 
    }
    sort(&q[1], &q[cntqu + 1], cmp), l = 1;
    for(int i = 1; i <= cntqu; ++i) {
        while(l < q[i].x) del(col[l++]);
        while(l > q[i].x) add(col[--l]);
        while(r < q[i].y) add(col[++r]);
        while(r > q[i].y) del(col[r--]);
        while(now < q[i].pre) doit(++now, i);
        while(now > q[i].pre) doit(now--, i);
        ans[q[i].z] = ret;
    }
    for(int i = 1; i <= cntqu; ++i)
        printf("%d\n", ans[i]);
    return 0;
} 

转载于:https://www.cnblogs.com/water-mi/p/10303807.html

weixin063传染病防控宣传微信小程序系统的设计与实现+springboot后端毕业源码案例设计 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值