zoukankan      html  css  js  c++  java
  • 题解——[AHOI2013]作业(莫队)

    题解——[AHOI2013]作业(莫队)

    有一段时间没写莫队,今天WZB分享这道题,ssw02一看,我可以用莫队水,写的挺快的

    欢迎转载ssw02的博客:https://www.cnblogs.com/ssw02/p/11823191.html

    题面

    给定长为N的序列 , M个询问,每次询问在 下标在[ L , R ]之间 , 数值在 [ a , b ]之间的数的种类和总数 。

    N, M都是在1e5 的范围内 。

    思路

    可以离线,数据支持根号算法,所以我们可以考虑分块 。 总数和如何统计 , 开个桶记录数值的个数 。 每次修改时用一个树状数组维护。支持区间查询即可 。

    有一点比较坑人, 之所以种类ssw02也用树状数组维护是因为只有[ a, b ]之间的修改才对当前答案有影响,所以我们不能够直接修改,应为上一次的种类并不能够继承到这次。我们需要重新统计(正好写了树状数组嘛)。另一种方法是在l , r移动的时候顺带处理不合法的贡献,把这些贡献删掉 。 由于数据较小,所以ssw02直接用2个树状数组分别维护2个答案即可 。

    代码

    #include<bits/stdc++.h>
    using namespace std ;
    #define ll long long
    const int MAXN = 100005 ; 
    inline int read(){
    	int s=0 ; char g=getchar() ; while( g>'9'||g<'0')g=getchar() ; 
    	while( g>='0'&&g<='9')s=s*10+g-'0',g=getchar() ; return s;
    }
    int N , M , a[MAXN] , tot , block , pos[MAXN] , vis[MAXN]  ;
    ll cnt[MAXN] , c[MAXN] , ans[MAXN] , anss[MAXN] ;  
    struct ap{
    	int l , r , id , a , b ; 
    }t[MAXN] ; 
    //-----------------
    void  add( int x , int y ){
    	for( ; x <= N ; x += x&-x )c[x] += y ; 
    }
    void  add2( int x, int y ){
    	for( ; x <= N ; x += x&-x )vis[x] += y ; 
    }
    ll ask_sum( int x ){
    	ll  tott = 0LL ; 
    	for( ; x ; x -= x&-x )
    	    tott += c[x] ;  
    	return tott ; 
    }
    ll ask_col( int x ){
    	ll tott = 0LL ; 
    	for( ; x ; x -= x&-x )tott += vis[x] ; 
    	return tott ;
    }
    //-----------------
    inline bool cmp( ap x , ap y ){
    	return ( pos[x.l] == pos[y.l] )?(x.r < y.r):(pos[x.l] < pos[y.l] ) ;
    }
    void  updata( int u , int opt , int now ){
    	if( opt ){
    		if( cnt[a[u]] == 0 )add2( a[u] , 1 ) ;
    		cnt[ a[u] ]++ ; add( a[u] , 1 ) ;  
    		return ;
    	}
    	else {
    		if( cnt[a[u]] == 1 )add2( a[u] , -1 ) ;
    		cnt[ a[u] ]-- ; add( a[u] , -1 ) ;
    	}
    }
    ll  ask( int l , int  r , int opt ){
    	if(opt)return ask_sum( r ) - ask_sum( l-1 ) ; 
    	else return ask_col( r ) - ask_col( l-1 ) ; 
    }
    void  Mo(){
    	for( int i = 1 , l = 1 , r = 0  ; i <= M ; ++i ){
    		while( t[i].l > l )updata( l++ , 0 , i ) ; 
    		while( t[i].l < l )updata( --l , 1 , i ) ; 
    		while( t[i].r > r )updata( ++r , 1 , i ) ; 
    		while( t[i].r < r )updata( r-- , 0 , i ) ; 
    		//for( int k = 1 ; k <= N ; ++k )cout<<c[k]<<" "; cout<<endl ;  
    		anss[ t[i].id ] = ask( t[i].a , t[i].b , 0 ) , ans[ t[i].id ] = ask( t[i].a , t[i].b , 1 ) ;
    	}
    }
    int main(){
    	N = read() , M = read() , block = sqrt(N) ;
    	for( int i = 1 ; i <= N ; ++i )a[i] = read() , pos[i] = ( i-1 )/block+1 ;  
    	for( int i = 1 ; i <= M ; ++i ){
    		t[i].l = read() , t[i].r = read() , t[i].a = read() , t[i].b = read() ,  t[i].id = i ;
    	}
    	sort( t+1 , t+M+1 , cmp ) ; 
    	Mo() ; 
    	for( int i = 1 ; i <= M ; ++i )
    	    printf("%lld %lld
    ",ans[i],anss[i]) ; 
    }
    
  • 相关阅读:
    docker配置国内加速器
    pwm原理与stm32控制
    【C语言】赋值表达式自增自减逗号表达式
    linux下利用paho.mqtt.c进行mqtt开发 #c编程
    linux下tcp #c编程
    windows下的linux子系统虚拟串口的使用
    linux下搭建mqtt服务器(mosquitto)
    linux下paho.mqtt.c下载安装
    树莓派&mysql数据库
    vscode+mysql数据库编程
  • 原文地址:https://www.cnblogs.com/ssw02/p/11823191.html
Copyright © 2011-2022 走看看