数颜色 [带修莫队]

链接

https://www.luogu.org/problem/P1903

题意

给定一个长度为n的序列,m次操作。需要支持两种操作:
1:把位置i上的数修改为v(从1开始编号)。
2:查询[L,R]内有多少种不同的数。

分析

这是一道带修莫队的模板题。
每个查询操作除了有左端点l和右端点r,还有一个时间t,
表示这个查询在第t个修改操作之后。
将这些查询(l,r,t)进行排序,以l/S为第一关键字,r/S为第二关键字,t为第三关键字。
其中S为分块的大小。
与普通莫队相比,当从上一个询问跳到当前的询问时,还要维护目前的修改数now。
当now小于查询的修改数时,就把没有进行的修改操作执行。
当now大于查询的修改数时,就将多出的已执行的修改进行回撤。
需要注意的是,如果执行或回撤的修改操作在目前的区间内,就要更新答案。
在修改数now与查询的修改数相等之后,再进行左右端点的移动。

复杂度分析:
n为序列长度,c为修改操作数,q为查询操作数,S为分块的大小。

  1. 修改数的移动:
    左端点分成n/S块,右端点分成n/S块,每个左右端点块最多移动c。
    因此移动次数为 O ( c ∗ n 2 / S 2 ) O(c*n^2/S^2) O(cn2/S2)
  2. 左端点的移动:
    在同一左端点块中,每次最多移动S;
    到下一左端点块时,最多移动2S。
    因此移动次数为 O ( q S ) O(qS) O(qS)
  3. 右端点的移动:
    在同一右端点块中,每次最多移动S;
    到下一右端点块时,每次最多移动2S;
    当左端点改变时,每次最多移动n。
    因此移动次数为 O ( q S + n 2 / S ) O(qS+n^2/S) O(qS+n2/S)

于是总移动次数为 O ( q S + c ∗ n 2 / S 2 + n 2 / S ) O(qS+c*n^2/S^2+n^2/S) O(qS+cn2/S2+n2/S)
由于不知道c和q的值,那么c和q统一用m代替,且假设n=m,
那么总移动次数就成了 O ( q S + n 3 / S 2 + n 2 / S ) O(qS+n^3/S^2+n^2/S) O(qS+n3/S2+n2/S)
S = n 2 / 3 S=n^{2/3} S=n2/3时,最优复杂度为 n 5 / 3 n^{5/3} n5/3

代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef double db;
template<class T>inline void MAX(T &x,T y){if(y>x)x=y;}
template<class T>inline void MIN(T &x,T y){if(y<x)x=y;}
template<class T>inline void rd(T &x){
	x=0;char o,f=1;
	while(o=getchar(),o<48)if(o==45)f=-f;
	do x=(x<<3)+(x<<1)+(o^48);
	while(o=getchar(),o>47);
	x*=f;
}
const int M=140005;
const int S=2500;
const int K=1e6+5;
struct node{
	int l,r,t,id;
	bool operator <(const node &A)const{
		if(l/S!=A.l/S)return l/S<A.l/S;
		if(r/S!=A.r/S){
			if(l/S&1)return r/S<A.r/S;
			else return r/S>A.r/S;
		}
		if(r/S&1)return t<A.t;
		else return t>A.t;
	}
}Q[M];
char str[M][5];
int n,m,A[M],pos[M],X[M],Y[M],ans[M];
int res,cnt[K];
void insert(int x){
	cnt[x]++;
	if(cnt[x]==1)res++;
}
void erase(int x){
	cnt[x]--;
	if(cnt[x]==0)res--;
}
int main(){
#ifndef ONLINE_JUDGE
	freopen("jiedai.in","r",stdin);
//	freopen("jiedai.out","w",stdout);
#endif
	rd(n),rd(m);
	for(int i=1;i<=n;i++)rd(A[i]);
	int l=1,r=0,now=0,tot=0;
	for(int i=1;i<=m;i++){
		scanf("%s",str[i]);
		int a,b;
		rd(a),rd(b);
		if(str[i][0]=='R'){
			now++;
			pos[now]=a;
			X[now]=A[a];
			Y[now]=b;
			A[a]=b;
		}
		else Q[++tot]=(node){a,b,now,i};
	}
	sort(Q+1,Q+1+tot);
	for(int i=1;i<=tot;i++){
		while(now<Q[i].t){
			now++;
			A[pos[now]]=Y[now];
			if(pos[now]>=l&&pos[now]<=r)erase(X[now]),insert(Y[now]);
		}
		while(now>Q[i].t){
			A[pos[now]]=X[now];
			if(pos[now]>=l&&pos[now]<=r)erase(Y[now]),insert(X[now]);
			now--;
		}
		while(r<Q[i].r)insert(A[++r]);
		while(l>Q[i].l)insert(A[--l]);
		while(r>Q[i].r)erase(A[r--]);
		while(l<Q[i].l)erase(A[l++]);
		ans[Q[i].id]=res;
	}
	for(int i=1;i<=m;i++)if(str[i][0]=='Q')printf("%d\n",ans[i]);
	return (0-0);
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
智慧农业是一种结合了现代信息技术,包括物联网、大据、云计算等,对农业生产过程进行智能化管理和监控的新模式。它通过各种传感器和设备采集农业生产中的关键据,如大气、土壤和水质参,以及生物生长状态等,实现远程诊断和精准调控。智慧农业的核心价值在于提高农业生产效率,保障食品安全,实现资源的可持续利用,并为农业产业的转型升级提供支持。 智慧农业的实现依赖于多个子系统,包括但不限于设施蔬菜精细化种植管理系统、农业技术资料库、据采集系统、防伪防串货系统、食品安全与质量追溯系统、应急追溯系统、灾情疫情防控系统、农业工作管理系统、远程诊断系统、监控中心、环境监测系统、智能环境控制系统等。这些系统共同构成了一个综合的信息管理和服务平台,使得农业生产者能够基于据做出更加科学的决策。 据采集是智慧农业的基础。通过手工录入、传感器自动采集、移动端录入、条码/RFID扫描录入、拍照录入以及GPS和遥感技术等多种方式,智慧农业系统能够全面收集农业生产过程中的各种据。这些据不仅包括环境参,还涵盖了生长状态、加工保存、检验检疫等环节,为农业生产提供了全面的据支持。 智慧农业的应用前景广阔,它不仅能够提升农业生产的管理水平,还能够通过各种应用系统,如库房管理、无公害监控、物资管理、成本控制等,为农业生产者提供全面的服务。此外,智慧农业还能够支持政府监管,通过发病报告、投入品报告、死亡报告等,加强农业产品的安全管理和质量控制。 面对智慧农业的建设和发展,存在一些挑战,如投资成本高、生产过程标准化难度大、据采集和监测的技术难题等。为了克服这些挑战,需要政府、企业和相关机构的共同努力,通过政策支持、技术创新和教育培训等手段,推动智慧农业的健康发展。智慧农业的建设需要明确建设目的,选择合适的系统模块,并制定合理的设备布署方案,以实现农业生产的智能化、精准化和高效化。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值