SD省队集训2019Day7之“五彩斑斓的世界”

五彩斑斓的世界(shinku)(Ynoi2015即便看不到未来)

题目描述

给你一个序列,每次查询一段区间中长度为 1,2,...10 的极长值域连续段个数
定义值域连续段为:
把区间里面所有数排序后去重,设排序后得到的序列为 b
如果对于二元组 (l,r) 满足 b[l],b[l+1],...b[r] 中每个数为前一个数 +1
而且对于二元组 (l,r+1),(l-1,r) 均不满足,我们称 (l,r) 为一个长度为
r-l+1 的极长值域连续段

思路

查询一个区间里面长为1 -> 10的极长值域连续段的个数
这个查询是和每个数在区间中位置无关的
然后如果(l,r)是一个极长值域连续段,那不存在(l-1,r),(l,r+1)这两个值域连续段
比如这个是区间的所有值映射到值域数组上:
0 0 0 1 0 0 1 1 1 0 1 0 0 1 1 1 0 1 1 1 1 1 0 1 0
(4,4)(7,9)(11,11)(14,16)(18,22)(24,24)就是所有的极长值域连续段
每次输出区间长为1,2…k的极长值域连续段段数

部分分

A

暴力
总复杂度O( nm )
得分约为10-25

B

莫队+bitset
莫队跑出区间的值域bitset,然后用四毛子来数区间每个值域连续段即可

总复杂度O( nm/w )
得分约为35-55

C

莫队+数据结构
用数据结构维护每个值域连续段,每次莫队转移的时候可以在数据结构上二分实现

总复杂度O( nsqrtmlogn )
得分约为35-55

D

不删除莫队
维护每个极长值域连续段向左,右的最远拓展的位置
每次如果只插入的话,可以O( 1 )维护
然后套用不删除莫队即可

总复杂度O( nsqrtm )
得分约为45-55

E

莫队+位运算优化
每次查询相当于是查询一个点往前,后有多少个连续的1
然后距离超过10就无意义了
这个可以用位运算优化
单次复杂度就是O( k/w ) = O( 1 )的了

总复杂度O( nsqrtm )
得分约为45-55

做法

考虑扫描线
扫右端点,开10个树状数组表示每个左端点的每个长度的极长值域连续段的个数
维护每个值最近的出现位置(在序列上的)
扫到一个位置的时候,暴力扫左,右10个

o_%E5%9B%BE%E7%89%871.png

相当于是把值在左右各10个的位置提出来,然后按照上次出现次数从大到小排序,然后一个一个插回来

o_%E5%9B%BE%E7%89%873.png

这里就是左端点<=5的时候出现了一个长为2的极长值域连续段
然后左端点<=3的时候出现了一个长为3的极长值域连续段
然后左端点<=2的时候出现了一个长为7的极长值域连续段
然后左端点<=1的时候出现了一个长为10的极长值域连续段

于是相当于是:
在这个新插入的点周围的长为2的极长值域连续段出现的左端点位置是[4,5]
长为3的极长值域连续段出现的左端点位置是[3,3]
长为2的极长值域连续段出现的左端点位置是[2,2]
长为1的极长值域连续段出现的左端点位置是[1,1]

然后把原来已经加了的贡献去掉,用这个新贡献替换就可以了
每次最多产生20个新的贡献
总复杂度O( 10(n+m)logn )

代码

#include <iostream>
#include <stdio.h>
#include <vector>
#include <algorithm>
#define lowbit( i ) i & -i
#define MAXN 1000010
#define MAXK 10
#define RG 11
#define MAXD 25

using namespace std;

struct point
{
    int x , y;
    point( int x , int y ) : x( x ) , y( y ) {}
    point() {}
} t[ MAXD ] , temp3[233];

inline bool cmp( const point & a , const point & b )
{
    return a.x == b.x ? a.y > b.y : a.x > b.x;
}

vector < point > q[ MAXN ];
int n , m , cnt , a[ MAXN ] , b[ ( MAXN + MAXK ) << 1 ] , last_pos[ MAXN << 1 ] , f[ MAXN ][ MAXK ] , g[ MAXK ][ MAXN ] , res[ MAXK ] , temp1[ MAXD ] , temp2[ MAXD ];
char ans[ MAXN ][ MAXD ];

inline void modify( int x , unsigned char y , char c )
{
    for( register int i = x ; i ; i ^= lowbit( i ) )
        f[i][y] += c;
}

inline void query( int x , int max_pos )
{
    for( register int i = 0 ; i < MAXK ; i++ ) res[i] = 0;
    for( register int i = x ; i <= max_pos ; i += lowbit( i ) )
        for( register unsigned char j = 0 ; j < MAXK ; j++ )
            res[j] += f[i][j];
}

int pos;

inline void Modify( int x , unsigned char y , char c )
{
    temp3[ pos++ ] = point( x , y );
    g[y][x] += c;
}

inline void make()
{
    for( register unsigned char i = 0 ; i < pos ; i++ )
        if( g[ temp3[i].y ][ temp3[i].x ] )
        {
            modify( temp3[i].x , temp3[i].y , g[ temp3[i].y ][ temp3[i].x ] );
            g[ temp3[i].y ][ temp3[i].x ] = 0;
        }
    pos = 0;
}

struct io               //快读
{
    char ibuf[1 << 25] , * s , obuf[1 << 24] , * t;
    int a[24];
    io() : t( obuf )
    {
        freopen( "shinku.in" , "rb" , stdin );
        freopen( "shinku.out" , "w" , stdout );
        s[ fread( s = ibuf , 1 , 1 << 25 , stdin ) ] = 0;
    }
    ~io()
    {
        fwrite( obuf , 1 , t - obuf , stdout );
    }
    inline int read()
    {
        register int u = 0;
        while( * s < 48 ) s++;
        while( * s > 32 )
            u = u * 10 + * s++ - 48;
        return u;
    }
    inline void print( register char * u )
    {
        for( register unsigned char i = 0 ; i < MAXK ; i++ )
            * t++ = * u++;
        * t++ = '\n';
    }
} ip;

#define read ip.read
#define print ip.print

int main()
{
    n = read() , m = read();
    for( register int i = 1 ; i <= n ; i++ ) a[i] = read();
    for( register int i = 1 ; i <= m ; i++ )
    {
        int l = read() , r = read();
        q[r].push_back( point( l , i ) );
    }
    for( register char i = 1 ; i <= MAXD ; i++ ) b[ ++cnt ] = 0;
    for( register int i = 1 ; i <= n ; i++ ) b[ ++cnt ] = a[i] , b[ ++cnt ] = a[i] + 1;
    sort( b + MAXD + 1 , b + cnt + 1 );
    cnt = unique( b + MAXD + 1 , b + cnt + 1 ) - b - 1;
    for( register int i = 1 ; i <= n ; i++ )
        a[i] = upper_bound( b + 1 , b + cnt + 1 , a[i] ) - b - 1;
    for( register int i = 1 ; i <= n ; i++ )
    {
        int c = 0;
        for( register char j = -RG ; j <= RG ; j++ )
            if( last_pos[ a[i] + j ] )
                t[ c++ ] = point( last_pos[ a[i] + j ] , j + RG );
        sort( t , t + c , cmp );
        t[c].x = 0;
        temp2[ RG ] = last_pos[ a[i] ] = i;
        Modify( i , 0 , 1 );
        Modify( t[0].x , 0 , -1 );
        for( register int j = 0 , a , b ; j < c && t[j].y != RG ; j++ )
        {
            temp1[ t[j].y ] = temp2[ t[j].y ] = i;
            for( a = 0 ; a < RG && temp1[ RG - a - 1 ] == i ; a++ );
            for( b = 0 ; b < RG && temp1[ RG + b + 1 ] == i ; b++ );
            if( a && a < RG )
                Modify( t[j].x , a - 1 , -1 ) , Modify( t[j + 1].x , a - 1 , 1 );
            if( b && b < RG )
                Modify( t[j].x , b - 1 , -1 ) , Modify( t[j + 1].x , b - 1 , 1 );
            if( a + b < MAXK )
                Modify( t[j].x , a + b , 1 ) , Modify( t[j + 1].x , a + b , -1 );
        }
        make();
        for( register vector < point > :: iterator j = q[i].begin() ; j != q[i].end() ; j++ )
        {
            query( j -> x , i );
            for( register int k = 0 ; k < MAXK ; k++ )
                ans[ j -> y ][k] = res[k] % 10 + 48;
        }
    }
    for( register int i = 1 ; i <= m ; i++ )
        print( ans[i] );
    return 0;
}

转载于:https://www.cnblogs.com/water-lift/p/10993779.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值