• 【题解】Luogu UVA12345 Dynamic len(set(a[L:R]))


    原题传送门

    这题要用动态莫队,我博客里有介绍

    这道题和luogu P1903 [国家集训队]数颜色 / 维护队列差不多,解法就在上面那篇博客里qaq

    主要的问题是如何排序?

    排序有三个关键字:

    1.左端点所在块数 2.右端点所在块数 3.在这次修改之前查询的次数

    在写莫队模板后面还要加上修改操作

    注意,序列是从0~n-1,查询是从l~r-1

    #include <bits/stdc++.h>
    #define N 50005
    using namespace std;
    inline int read()
    {
    	register int x=0,f=1;register char ch=getchar();
    	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    	while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
    	return x*f;
    }
    inline void write(register int x)
    {
    	if(!x)putchar('0');if(x<0)x=-x,putchar('-');
    	static int sta[25];int tot=0;
    	while(x)sta[tot++]=x%10,x/=10;
    	while(tot)putchar(sta[--tot]+48);
    }
    struct change{
    	int pos,pre,suf;
    }ch[N];
    struct query{
    	int l,r,id,time,bll,blr;
    }q[N];
    int a[N],blocksize=0,num[1000001],ans[N];
    inline bool cmp(register query a,register query b)
    {
    	return a.bll!=b.bll?a.bll<b.bll:(a.blr!=b.blr?a.blr<b.blr:a.time<b.time);
    }
    int main()
    {
    	int n=read(),m=read(),tota=0,totb=0;
    	for(register int i=1;i<=n;++i)
    		a[i]=read();
    	for(register int i=1;i<=m;++i)
    	{
    		char cha=getchar();
    		while(cha!='Q'&&cha!='M')
    			cha=getchar();
    		if(cha=='Q')
    		{
    			int l=read()+1,r=read();
    			++tota;
    			q[tota]=(query){l,r,tota,totb,0,0}; 
    		} 
    		else
    		{
    			int pos=read()+1,x=read();
    			++totb;
    			ch[totb]=(change){pos,a[pos],x};
    			a[pos]=x;
    		}
    	}
    	blocksize=ceil(exp((log(n)+log(tota))/3));
    	for(register int i=1;i<=tota;++i)
    		q[i].bll=(q[i].l-1)/blocksize+1,q[i].blr=(q[i].r-1)/blocksize+1;
    	for(register int i=totb;i>=1;--i)
    		a[ch[i].pos]=ch[i].pre;
    	sort(q+1,q+tota+1,cmp);
    	int l=1,r=0,t=0,sum=0;
    	for(register int i=1;i<=tota;++i)
    	{
    		int ll=q[i].l,rr=q[i].r,tt=q[i].time;
    		while(ll<l)
    			sum+=!num[a[--l]]++;
    		while(ll>l)
    			sum-=!--num[a[l++]];
    		while(rr>r)
    			sum+=!num[a[++r]]++;
    		while(rr<r)
    			sum-=!--num[a[r--]];
    		while(t<tt)
    		{
    			int pos=ch[++t].pos;
    			if(l<=pos&&pos<=r)
    				sum-=!--num[a[pos]];
    			a[pos]=ch[t].suf;
    			if(l<=pos&&pos<=r)
    				sum+=!num[a[pos]]++;
    		}
    		while(t>tt)
    		{
    			int pos=ch[t].pos;
    			if(l<=pos&&pos<=r)
    				sum-=!--num[a[pos]];
    			a[pos]=ch[t--].pre;
    			if(l<=pos&&pos<=r)
    				sum+=!num[a[pos]]++;
    		}
    		ans[q[i].id]=sum;
    	}
    	for(register int i=1;i<=tota;++i)
    		write(ans[i]),printf("
    ");
    	return 0;
    }
    
  • 相关阅读:
    BZOJ1029:[JSOI2007]建筑抢修(贪心,堆)
    1054. [HAOI2008]移动玩具【BFS】
    1297. [SCOI2009]迷路【矩阵乘法】
    1192. [HNOI2006]鬼谷子的钱袋【进制】
    2243. [SDOI2011]染色【树链剖分】
    1051. [HAOI2006]受欢迎的牛【强连通分量】
    codevs 2074 营救 WW
    codevs 1191 数轴染色
    codevs 2855 游乐园的迷宫 bfs
    codevs 2806 红与黑
  • 原文地址:https://www.cnblogs.com/yzhang-rp-inf/p/10004467.html
Copyright © 2020-2023  润新知