• loj #6283. 数列分块入门 7


    #6283. 数列分块入门 7

    题目描述

    给出一个长为 nnn 的数列,以及 nnn 个操作,操作涉及区间乘法,区间加法,单点询问。

    输入格式

    第一行输入一个数字 nnn。

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

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

    若 opt=0mathrm{opt} = 0opt=0,表示将位于 [l,r][l, r][l,r] 的之间的数字都加 ccc。

    若 opt=1mathrm{opt} = 1opt=1,表示将位于 [l,r][l, r][l,r] 的之间的数字都乘 ccc。

    若 opt=2mathrm{opt} = 2opt=2,表示询问 ara_rar​​ 的值 mod 10007mod 10007mod 10007(lll 和 ccc 忽略)。

    输出格式

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

    样例

    样例输入

    7
    1 2 2 3 9 3 2
    0 1 3 1
    2 1 3 1
    1 1 4 4
    0 1 7 2
    1 2 6 4
    1 1 6 5
    2 2 6 4

    样例输出

    3
    100

    数据范围与提示

    对于 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
    #define mod 10007
    using namespace std;
    int n,block,a[maxn],pos[maxn],add[maxn],mul[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=findl(id),r=findr(id);
        for(int i=l;i<=r;i++){
            a[i]=1LL*a[i]*mul[id]%mod;
            a[i]=(a[i]+add[id])%mod;
        }
        mul[id]=1;
        add[id]=0;
    }
    void modify1(int l,int r,int c){
        reset(pos[l]);
        for(int i=l;i<=min(findr(pos[l]),r);i++)(a[i]+=c)%=mod;
        if(pos[l]==pos[r])return;
        reset(pos[r]);
        for(int i=findl(pos[r]);i<=r;i++)(a[i]+=c)%=mod;
        for(int i=pos[l]+1;i<=pos[r]-1;i++)
            (add[i]+=c)%=mod;
    }
    void modify2(int l,int r,int c){
        reset(pos[l]);
        for(int i=l;i<=min(findr(pos[l]),r);i++)a[i]=1LL*a[i]*c%mod;
        if(pos[l]==pos[r])return;
        reset(pos[r]);
        for(int i=findl(pos[r]);i<=r;i++)a[i]=1LL*a[i]*c%mod;
        for(int i=pos[l]+1;i<=pos[r]-1;i++){
            add[i]=1LL*add[i]*c%mod;
            mul[i]=1LL*mul[i]*c%mod;
        }
    }
    int query(int x){
        int id=0,suf=0;
        while(1){
            suf+=block;
            if(suf>=x){
                if(suf>n)id=pos[n];
                else id=pos[suf];
                break;
            }
        }
        return (1LL*a[x]*mul[id]%mod+add[id])%mod;
    }
    int main(){
        scanf("%d",&n);
        for(int i=1;i<=n;i++)scanf("%d",&a[i]);
        block=sqrt(n);
        for(int i=1;i<=n;i++)pos[i]=(i-1)/block+1,mul[i]=1;
        int op,l,r,c;
        for(int i=1;i<=n;i++){
            scanf("%d%d%d%d",&op,&l,&r,&c);
            if(op==0)modify1(l,r,c);
            else if(op==1)modify2(l,r,c);
            else printf("%d
    ",query(r));
        }
        return 0;
    }
  • 相关阅读:
    C#listbox使用方法
    poj 3894 System Engineer (二分图最大匹配--匈牙利算法)
    Java实现 蓝桥杯VIP 算法训练 连接字符串
    Java实现 蓝桥杯VIP 算法训练 连接字符串
    Java实现 蓝桥杯VIP 算法训练 比较字符串
    Java实现 蓝桥杯VIP 算法训练 比较字符串
    Java实现 蓝桥杯VIP 算法训练 比较字符串
    Java实现 蓝桥杯VIP 算法训练 比较字符串
    Java实现 蓝桥杯VIP 算法训练 比较字符串
    Java实现 蓝桥杯VIP 算法训练 黑白无常
  • 原文地址:https://www.cnblogs.com/thmyl/p/8966672.html
Copyright © 2020-2023  润新知