Loj 6283. 数列分块入门 7

链接:https://loj.ac/problem/6283

思路:

多重标记下放,之前写过线段树的多重标记,两个思路是一样的,都是优先处理乘法操作,如果当前块出现乘法操作,那么加法标记也要乘上乘法标记,这样运算的时候就可以直接乘上乘法标记加上加法标记

如果当前块出现加法操作,那只对加法标记有影响,加上去就好了

 

实现代码;

复制代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int M = 1e5+10;
int mtag[M],atag[M],a[M],bl[M],n,block;
const int mod = 10007;
void resert(int x){
    for(int i = (x-1)*block+1;i <= min(x*block,n);i ++)
        a[i] = (a[i]*mtag[x] + atag[x])%mod;
    atag[x] = 0; mtag[x] = 1;
}

void update(int f,int l,int r,int c){
     resert(bl[l]);
     for(int i = l;i <= min(bl[l]*block,r);i ++){
        if(f == 1) a[i] = (a[i]*c)%mod;
        else a[i] = (a[i]+c)%mod;
     }
     if(bl[l] != bl[r]){
        resert(bl[r]);
        for(int i = (bl[r]-1)*block+1;i <= r;i ++){
            if(f == 1) a[i] = (a[i]*c)%mod;
            else a[i] = (a[i] + c)%mod;
         }
     }
     for(int i = bl[l]+1;i <= bl[r]-1;i ++){
        if(f == 1) {
            atag[i] = (atag[i]*c)%mod; mtag[i] = (mtag[i]*c)%mod;
        }
        else atag[i] = (atag[i]+c)%mod;
     }
}

int main()
{
    int f,l,r,c;
    scanf("%d",&n);
    block = sqrt(n);
    for(int i = 1;i <= n;i ++)  scanf("%d",&a[i]);
    for(int i = 1;i <= n;i ++)  bl[i] = (i-1)/block + 1;
    for(int i = 1;i <= bl[n];i ++)  mtag[i] = 1,atag[i] = 0;
    for(int i = 1;i <= n;i ++){
        scanf("%d%d%d%d",&f,&l,&r,&c);
        if(f == 2) printf("%d\n",(a[r]*mtag[bl[r]] + atag[bl[r]])%mod);
        else update(f,l,r,c);
    }
    return 0;
}
复制代码

 

posted @   冥想选手  阅读(184)  评论(0编辑  收藏  举报
编辑推荐:
· Linux glibc自带哈希表的用例及性能测试
· 深入理解 Mybatis 分库分表执行原理
· 如何打造一个高并发系统?
· .NET Core GC压缩(compact_phase)底层原理浅谈
· 现代计算机视觉入门之:什么是图片特征编码
阅读排行:
· 手把手教你在本地部署DeepSeek R1,搭建web-ui ,建议收藏!
· Spring AI + Ollama 实现 deepseek-r1 的API服务和调用
· 数据库服务器 SQL Server 版本升级公告
· 程序员常用高效实用工具推荐,办公效率提升利器!
· C#/.NET/.NET Core技术前沿周刊 | 第 23 期(2025年1.20-1.26)
点击右上角即可分享
微信分享提示