• loj #6284. 数列分块入门 8


    #6284. 数列分块入门 8

    题目描述

    给出一个长为 nnn 的数列,以及 nnn 个操作,操作涉及区间询问等于一个数 ccc 的元素,并将这个区间的所有元素改为 ccc。

    输入格式

    第一行输入一个数字 nnn。

    第二行输入 nnn 个数字,第 i 个数字为 aia_iai​​,以空格隔开。

    接下来输入 nnn 行询问,每行输入三个数字 lll、rrr、ccc,以空格隔开。

    表示先查询位于 [l,r][l,r][l,r] 的数字有多少个是 ccc,再把位于 [l,r][l,r][l,r] 的数字都改为 ccc。

    输出格式

    对于每次询问,输出一行一个数字表示答案。

    样例

    样例输入

    4
    1 2 2 4
    1 3 1
    1 4 4
    1 2 2
    1 4 2

    样例输出

    1
    1
    0
    2

    数据范围与提示

    对于 100% 100\%100% 的数据,1≤n≤100000,−231≤others 1 leq n leq 100000, -2^{31} leq mathrm{others}1n100000,231​​others、ans≤231−1 mathrm{ans} leq 2^{31}-1ans231​​1。

    维护区间是否是连续的相同值

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #define maxn 100010
    using namespace std;
    int n,m,block,a[maxn],tag[maxn],pos[maxn];
    bool cover[maxn];
    int findl(int id){return (id-1)*block+1;}
    int findr(int id){return min(id*block,n);}
    void reset(int id,int l,int r,int v1,int v2){
        for(int i=findl(id);i<l;i++)a[i]=v1;
        for(int i=l;i<=r;i++)a[i]=v2;
        for(int i=r+1;i<=findr(id);i++)a[i]=v1;
        cover[id]=0;
    }
    int count(int l,int r,int v){
        int res=0;
        for(int i=l;i<=r;i++){
            if(a[i]==v)res++;
            else a[i]=v;
        }
        return res;
    }
    int get(int l,int r,int v){
        if(cover[pos[l]]){
            if(tag[pos[l]]==v)return r-l+1;
            else reset(pos[l],l,r,tag[pos[l]],v);
        }
        else return count(l,r,v);
        return 0;
    }
    int query(int l,int r,int v){
        int res=get(l,min(findr(pos[l]),r),v);
        if(pos[l]!=pos[r])res+=get(findl(pos[r]),r,v);
        for(int i=pos[l]+1;i<=pos[r]-1;i++){
            if(cover[i]){
                if(tag[i]==v)res+=pos[l]==pos[n]?m:block;
                else tag[i]=v;
            }
            else {
                res+=count(findl(i),findr(i),v);
                cover[i]=1;
                tag[i]=v;
            }
        }
        return res;
    }
    int main(){
        scanf("%d",&n);
        block=sqrt(n);
        for(int i=1;i<=n;i++){
            pos[i]=(i-1)/block+1;
            scanf("%d",&a[i]);
        }
        m=n-(pos[n]-1)*block;
        int l,r,c;
        for(int i=1;i<=n;i++){
            scanf("%d%d%d",&l,&r,&c);
            printf("%d
    ",query(l,r,c));
        }
        return 0;
    }
  • 相关阅读:
    YourSQLDba低版本的一个Bug的浅析
    VMware虚拟机(Linux)如何找出系统中磁盘设备对应的硬盘
    SSH登录报pam_unix(sshd:auth): authentication failure的案例
    Linux shell中如何给文本加上行号呢
    Linux查看系统块大小
    存储基础知识:扇区与块/簇
    SQL Server中GETDATE转换时间时注意事项
    SQL Server 2008 R2执行存储过程sp_MailItemResultSets引起大量PREEMPTIVE_OS_WAITFORSINGLEOBJEC等待
    Timeout expired. The timeout period elapsed prior to obtaining a connection from the pool
    SQL Server 2014下Database Mail Engine进程消耗大量CPU资源
  • 原文地址:https://www.cnblogs.com/thmyl/p/8967864.html
Copyright © 2020-2023  润新知