zoukankan      html  css  js  c++  java
  • 分块算法板子luogu1903

    https://www.luogu.org/problemnew/show/1903

    用pre[i]数组记录上一次和当前i同色的位置

    查询[l,r],若pre[i]<r,则说明在[l,i)区间内没用和i同色的,则++ans

    于是就可以大胆地分块

    对于每一块按照pre[i]排序,再进行二分了

    复杂度O(qsqrt(n)log(n)).

    #include<stdio.h>
    #include<math.h>
    #include<algorithm>
    #define FOR(i,s,t) for(register int i=s;i<=t;++i)
    using std::sort;
    using std::lower_bound;
    const int N=10011;
    const int M=1000011;
    inline int min(int a,int b){
    	return a<b?a:b;
    }
    int n,q,m,blo;
    int c[N],pos[N],pre[N],b[N],last[M];
    inline int find(int x,int v){
    	int l=(x-1)*blo+1,r=min(x*blo,n);
    	return lower_bound(pre+l,pre+r+1,v)-pre-l;
    }
    inline void reset(int x){
    	int l=(x-1)*blo+1,r=min(x*blo,n);
    	FOR(i,l,r)pre[i]=b[i];
    	sort(pre+l,pre+r+1);
    }
    inline void build(){
    	FOR(i,1,n){
    		b[i]=last[c[i]];
    		last[c[i]]=i;
    		pos[i]=(i-1)/blo+1;
    	}
    	FOR(i,1,m)reset(i);
    }
    inline int ask(int l,int r){
    	int ans=0;
    	if(pos[l]==pos[r]){
    		FOR(i,l,r)if(b[i]<l)++ans;
    		return ans;
    	}
    	for(register int i=l;i<=blo*pos[l];++i)if(b[i]<l)++ans;
    	for(register int i=blo*(pos[r]-1)+1;i<=r;++i)if(b[i]<l)++ans;
    	for(register int i=pos[l]+1;i<pos[r];++i)ans+=find(i,l);
    	return ans;
    }
    inline void change(int x,int v){
    	FOR(i,1,n)last[c[i]]=0;
    	c[x]=v;
    	FOR(i,1,n){
    		int t=b[i];
    		b[i]=last[c[i]];
    		if(t!=b[i])reset(pos[i]);
    		last[c[i]]=i;
    	}
    }
    int main(){
    	scanf("%d%d",&n,&q);
    	FOR(i,1,n)scanf("%d",c+i);
    	blo=int(sqrt(n));
    	m=n%blo?(n/blo+1):n/blo;
    	build();
    	char ch[5];int x,y;
    	while(q--){
    		scanf("%s%d%d",ch,&x,&y);
    		if(ch[0]=='Q')printf("%d
    ",ask(x,y));
    		else change(x,y);
    	}
    	return 0;
    }
    

      

    补一份带修莫队板子

    #include<stdio.h>
    #include<math.h>
    #include<algorithm>
    #define FOR(i,s,t) for(register int i=s;i<=t;++i)
    using std::swap;
    using std::sort;
    const int N=10011,M=300011;
    int blo,times,n,m,l,r,tot,now,res;
    struct qs{
    	int l,r,t,id;
    	inline bool operator<(qs A)const{
    		if(l/blo!=A.l/blo)return l<A.l;
    		if(r/blo!=A.r/blo)return r<A.r;
    		if(t/blo!=A.t/blo)return t<A.t;
    		return id<A.id;
    	}
    }q[N];
    struct cg{int p,x;}c[N];
    int a[N],ans[N],hv[M];
    char Q[5];
    inline void add(int x){if(!hv[x])++res;++hv[x];}
    inline void del(int x){--hv[x];if(!hv[x])--res;}
    inline void change(int x,int i){
    	if(c[x].p>=q[i].l&&c[x].p<=q[i].r){
    		--hv[a[c[x].p]];if(!hv[a[c[x].p]])--res;
    		if(!hv[c[x].x])++res;++hv[c[x].x];
    	}
    	swap(c[x].x,a[c[x].p]);
    }
    int main(){
    	scanf("%d%d",&n,&m);blo=pow(n,2.00/3.00);
    	FOR(i,1,n)scanf("%d",a+i);
    	FOR(i,1,m){
    		scanf("%s%d%d",Q,&l,&r);
    		if(Q[0]=='Q')
    			q[++tot]=(qs){l,r,times,tot};
    		else c[++times]=(cg){l,r};
    	}
    	sort(q+1,q+tot+1);
    	l=1;r=0;now=0;
    	FOR(i,1,m){
    		while(l<q[i].l)del(a[l++]);while(q[i].l<l)add(a[--l]);
    		while(r<q[i].r)add(a[++r]);while(q[i].r<r)del(a[r--]);
    		while(now<q[i].t)change(++now,i);while(q[i].t<now)change(now--,i);
    		ans[q[i].id]=res;
    	}
    	FOR(i,1,tot)printf("%d
    ",ans[i]);
    	return 0;
    }
    

      

    线段树+bitset

    #include<stdio.h>
    #include<bitset>
    #include<algorithm>
    #define FOR(i,s,t) for(register int i=s;i<=t;++i)
    using std::bitset;
    using std::sort;
    using std::unique;
    using std::lower_bound;
    const int N=10011;
    bitset<N>s[N<<2],ans;
    int a[N];
    int b[N<<2];
    inline void build(int k,int l,int r){
        if(l==r){
            s[k][a[l]]=1;
            return ;
        }
        int mid=(l+r)>>1;
        build(k<<1,l,mid);
        build(k<<1|1,mid+1,r);
        s[k]=s[k<<1]|s[k<<1|1];
    }
    int n,m,cnt;
    inline void change(int k,int l,int r,int x,int v){
        if(l==r){
            s[k][a[l]]=0;
            s[k][a[l]=v]=1;
            return;
        }
        int mid=(l+r)>>1;
        x<=mid?change(k<<1,l,mid,x,v):change(k<<1|1,mid+1,r,x,v);
        s[k]=s[k<<1]|s[k<<1|1];
    }
    inline void query(int k,int l,int r,int x,int y){
        if(x<=l&&r<=y){
            ans|=s[k];
            return;
        }
        int mid=(l+r)>>1;
        if(x<=mid) query(k<<1,l,mid,x,y);
        if(mid<y) query(k<<1|1,mid+1,r,x,y);
        
    }
    struct question{
        char c;
        int x;
        int y;
    }q[N];
    inline void disc_init(){
        sort(b+1,b+cnt+1);
        cnt=unique(b+1,b+cnt+1)-b-1;
    }
    inline int read(){
        char c;while(c=getchar(),c==' '||c=='
    ');int data=c-48;
        while(c=getchar(),c>='0'&&c<='9')data=(data<<1)+(data<<3)+c-48;return data;
    }
    int main(){
        scanf("%d%d
    ",&n,&m);
        FOR(i,1,n)b[++cnt]=a[i]=read();
        scanf("
    ");
        FOR(i,1,m){
            q[i].c=getchar();
            q[i].x=read();q[i].y=read();
            scanf("
    ");
            if(q[i].c=='R')b[++cnt]=q[i].y;
        }
        disc_init();
        FOR(i,1,n)a[i]=lower_bound(b+1,b+cnt+1,a[i])-b;
        build(1,1,n);
        FOR(i,1,m){
            if(q[i].c=='Q'){
                ans.reset();
                query(1,1,n,q[i].x,q[i].y);
                printf("%d
    ",ans.count());
            }
            else{
                q[i].y=lower_bound(b+1,b+cnt+1,q[i].y)-b;
                change(1,1,n,q[i].x,q[i].y);
            }
        }
        return 0;
    }
    

      

  • 相关阅读:
    SQLServer性能诊断与调优
    (转).NET面试题整理之基础篇
    (转)[茗洋芳竹]程序员常用不常见很难得的地址大全,博主很辛苦
    (转)页面过度动画效果大集合
    (转)软件开发和团队”最小模式”初探2-6人模型(下)
    silverlight 乐动魔方 实战九 .
    (转)js+flash实现手写输入功能特效
    (转)软件开发和团队”最小模式”初探2-6人模型(上)
    (转)我眼中的PM
    silverlight 乐动魔方 实战十 .
  • 原文地址:https://www.cnblogs.com/Stump/p/7900591.html
Copyright © 2011-2022 走看看