zoukankan      html  css  js  c++  java
  • luogu1903

    (带修莫队题....有点卡常需要调整块的大小....最合适的位置为sz=(n^(2/3)),可通过基本不等式证明,(明天补树套树做法

    题解:权值很小,数组可解决(权值过大应该考虑离散化),然后就是基本带修操作

    #include <bits/stdc++.h>
    #define ll long long
    #define s second
    #define f first
    #define inc(i,l,r) for(int i=l;i<=r;i++)
    #define dec(i,r,l) for(int i=r;i>=l;i--)
    const int MAXN=5e4+10;
    const int NM=1e6+100;
    using namespace std;
    ll read(){  
        ll x=0,f=1;char ch=getchar();  
        while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}  
        while(isdigit(ch))x=x*10+ch-'0',ch=getchar();  
        return f*x;  
    }
    int n,m;
    int a[MAXN],b[MAXN];
    typedef struct node{
    	int pos,x,y;
    }node;
    node d1[MAXN],d2[MAXN];
    int p[MAXN],flag[NM];
    typedef struct Node{
    	int l,r,t,id;
    	friend bool operator<(Node aa,Node bb){
    		if(p[aa.l]==p[bb.l]&&p[aa.r]==p[bb.r]) return aa.t<bb.t;
    		else if(p[aa.l]==p[bb.l]) return p[aa.r]<p[bb.r];
    		else return p[aa.l]<p[bb.l];
    	}
    }Node;
    Node que[MAXN];
    int ans[MAXN],ans1;
    void join(int l,int r,int pos){
    	if(l<=d1[pos].pos&&d1[pos].pos<=r){
    		flag[d1[pos].x]--;
    		if(!flag[d1[pos].x])ans1--;
    		flag[d1[pos].y]++;
    		if(flag[d1[pos].y]==1)ans1++;
    	}
    	a[d1[pos].pos]=d1[pos].y;
    }
    void erase(int l,int r,int pos){
    	if(l<=d2[pos].pos&&d2[pos].pos<=r){
    		flag[d2[pos].x]--;
    		if(!flag[d2[pos].x])ans1--;
    		flag[d2[pos].y]++;
    		if(flag[d2[pos].y]==1)ans1++;		
    	}
    	a[d2[pos].pos]=d2[pos].y;
    }
    int main(){
    	n=read(),m=read();int sz=(int)pow(n,2.0/3);
    	for(int i=1;i<=n;i++)p[i]=(i-1)/sz+1;
    	inc(i,1,n)a[i]=read(),b[i]=a[i];
    	int t=0,pos,vul;char ch;int cnt=0;
    	for(int i=1;i<=m;i++){
    		scanf(" %c",&ch);
    		if(ch=='Q'){
    			que[++cnt].l=read();que[cnt].r=read();que[cnt].id=i;que[cnt].t=t;
    		}
    		else{
    			t++;pos=read(),vul=read();
    			d1[t].pos=pos;d1[t].x=b[pos];d1[t].y=vul;
    			d2[t].pos=pos;d2[t].x=vul;d2[t].y=b[pos];
    			b[pos]=vul;
    		}
    		ans[i]=-1;
    	}
    	sort(que+1,que+cnt+1);
    	int L=1,R=0,T=0;ans1=0;
    	for(int i=1;i<=cnt;i++){
    		while(que[i].t<T){
    			erase(L,R,T);T--;
    		}
    		while(que[i].t>T){
    			T++;join(L,R,T);
    		}
    		while(que[i].l>L){
    			flag[a[L]]--;
    			if(!flag[a[L]])ans1--;
    			L++;
    		}
    		while(que[i].l<L){
    			L--;flag[a[L]]++;
    			if(flag[a[L]]==1)ans1++;
    		}
    		while(que[i].r<R){
    			flag[a[R]]--;
    			if(!flag[a[R]])ans1--;
    			R--;
    		}
    		while(que[i].r>R){
    			R++;flag[a[R]]++;
    			if(flag[a[R]]==1)ans1++;
    		}
    		ans[que[i].id]=ans1;
    	}
    	for(int i=1;i<=m;i++)if(ans[i]>=0)printf("%d
    ",ans[i]);
    	return 0;
    }
    

      

  • 相关阅读:
    同步和异步有何异同,在什么情况下分别使用他们?
    Android 缓存处理
    Android常用的设计模式概念
    Android常见的设计模式详解
    Android中的五大布局
    几种常见的引用概念
    面向对象的思想概述
    Android系统架构的简单描述
    display:none;与visibility:hidden;的区别
    块级元素和行内元素的区别
  • 原文地址:https://www.cnblogs.com/wang9897/p/9049010.html
Copyright © 2011-2022 走看看