zoukankan      html  css  js  c++  java
  • #6284. 数列分块入门 8

    题目链接:https://loj.ac/problem/6284

    题目描述

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

    输入格式

    第一行输入一个数字 n

    第二行输入 n个数字,第 i 个数字为 ai,以空格隔开。

    接下来输入 n 行询问,每行输入三个数字 l、r、c,以空格隔开。

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

    输出格式

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

    样例

    样例输入

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

    样例输出

    1
    1
    0
    2

    思路:和第5题差不多,用一个标记数组flag标记整块的值。没有标记和不完整块的暴力找,因为没有标记暴力找
    的时间复杂度就O(n)。注意不完整块需要更新现在的值,因为有可能前面整块出现,导致没有更新值,但flag标记了。
    代码:
    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #define inf 0x3f3f3f3f
    using namespace std;
    typedef long long ll;
    const int maxn=1e5+10;
    int a[maxn],pos[maxn],flag[maxn],n,block,ans;
    
    void reset(int x)//更新不完整块的值 
    {
        if(flag[pos[x]]==-1)
            return;
        else
        {
            for(int i=(pos[x]-1)*block+1;i<=pos[x]*block;i++)
                a[i]=flag[pos[x]];
        }
        flag[pos[x]]=-1;//记得更新标记值 
    }
    int query(int l,int r,int c)
    {
        ans=0;
        reset(l);
        for(int i=l;i<=min(pos[l]*block,r);i++)//左不完整块暴力加 
        {
            if(a[i]==c)
                ans++;
            a[i]=c;//记得改变值 
        }
        if(pos[l]!=pos[r])//右不完整块暴力加 
        {
            reset(r);
            for(int i=(pos[r]-1)*block+1;i<=r;i++)
            {
                if(a[i]==c)
                    ans++;
                a[i]=c;
            }
        }
        for(int i=pos[l]+1;i<=pos[r]-1;i++)//完整块用flag处理 
        {
            if(flag[i]==-1)//没有标记,暴力找 
            {
                for(int j=(i-1)*block+1;j<=i*block;j++)
                {
                    if(a[j]==c)
                        ans++;
                    a[j]=c;
                }
            }
            else if(flag[i]==c)//整块相等 
                ans+=block; 
            flag[i]=c;//记得标记更新 
        }
        return ans;
    }
    int main()
    {
        scanf("%d",&n);
        block=sqrt(n);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
            pos[i]=(i-1)/block+1;
        }    
        for(int i=0;i<=pos[n];i++)
            flag[i]=-1;
        int l,r,c;
        for(int i=0;i<n;i++)
        {
            scanf("%d%d%d",&l,&r,&c);
            printf("%d
    ",query(l,r,c));
        }
        return 0;
    } 
  • 相关阅读:
    串口通信理论知识
    串口通信基础
    串口中断程序步骤及代码
    Django之CRM项目Day6-公私户转换问题解决 班主任功能
    Django之CRM项目Day5-跳转页面 跟进记录 报名记录
    Django之CRM项目Day4-编辑客户 公私户 模糊查询
    Django之CRM项目Day3-客户展示及分页
    Django的ModelForm
    Django相关面试题
    Django基础自测
  • 原文地址:https://www.cnblogs.com/xiongtao/p/9800088.html
Copyright © 2011-2022 走看看