1970: #6029. 「雅礼集训 2017 Day1」市场

题目描述

从前有一个贸易市场,在一位执政官到来之前都是非常繁荣的,自从他来了之后,发布了一系列奇怪的政令,导致贸易市场的衰落。

有 n nn 个商贩,从 0∼n−1 0 \sim n - 10∼n−1 编号,每个商贩的商品有一个价格 ai a_iai,有两种政令:

  1. l,r,c l, r, cl,r,c,对于 i∈[l,r],ai←ai+c i \in [l, r], a_i \leftarrow a_i + ci∈[l,r],ai←ai+c
  2. l,r,d l, r, dl,r,d,对于 i∈[l,r],ai←⌊ai/d⌋ i \in [l, r], a_i \leftarrow \lfloor {a_i}/{d} \rfloori∈[l,r],ai←⌊ai/d⌋

现在有一个外乡的旅客想要了解贸易市场的信息,有两种询问方式:

  1. 给定 l,r l, rl,r,求 mini∈[l,r]ai \min_{i \in [l, r]} a_imini∈[l,r]ai
  2. 给定 l,r l, rl,r,求 ∑i∈[l,r]ai \sum_{i\in [l, r]} a_i∑i∈[l,r]ai

输入

第一行为两个空格隔开的整数 n,q n, qn,q 分别表示商贩个数和政令 + 询问个数。
第二行包含 n nn 个由空格隔开的整数 a0∼an−1 a_0 \sim a_{n - 1}a0∼an−1
接下来 q qq 行,每行表示一个操作,第一个数表示操作编号 1∼4 1 \sim 41∼4,接下来的输入和问题描述一致。

输出

对于每个 3、4 操作,输出询问答案。

样例输入 

10 10
-5 -4 -3 -2 -1 0 1 2 3 4
1 0 4 1
1 5 9 1
2 0 9 3
3 0 9
4 0 9
3 0 1
4 2 3
3 4 5
4 6 7
3 8 9

样例输出 

-2
-2
-2
-2
0
1
1

提示

对于 30% 30\%30% 的数据,n,q≤103 n, q \leq 10 ^ 3n,q≤103;
对于 60% 60\%60% 的数据,保证数据随机;
对于 100% 100\%100% 的数据,1≤n,q≤105,0≤l≤r≤n−1,c∈[−104,104],d∈[2,109] 1 \leq n, q \leq 10 ^ 5, 0 \leq l \leq r \leq n - 1, c \in [-10 ^ {4}, 10 ^ 4], d \in [2, 10 ^ 9]1≤n,q≤105,0≤l≤r≤n−1,c∈[−104,104],d∈[2,109]

#include <bits/stdc++.h>
 
const int MAXN=1e5+10;
typedef long long intEx;
 
struct Node{
    int l;
    int r;
    int max;
    int min;
    int add;
    intEx sum;
    Node* lch;
    Node* rch;
    Node(int,int);
    void Add(int);
    void PushDown();
    void Maintain();
    void Add(int,int,int);
    void Div(int,int,int);
    int QueryMin(int,int);
    intEx QuerySum(int,int);
};
 
int n;
int q;
int a[MAXN];
 
int ReadInt();
inline int FDiv(int,int);
 
int main(){
    n=ReadInt(),q=ReadInt();
    for(int i=0;i<n;i++)
        a[i]=ReadInt();
    Node* N=new Node(0,n-1);
    for(int i=0;i<q;i++){
        int t=ReadInt(),l=ReadInt(),r=ReadInt();
        if(t==1){
            int d=ReadInt();
            N->Add(l,r,d);
        }
        else if(t==2){
            int d=ReadInt();
            N->Div(l,r,d);
        }
        else if(t==3)
            printf("%d\n",N->QueryMin(l,r));
        else if(t==4)
            printf("%lld\n",N->QuerySum(l,r));
    }
    return 0;
}
 
intEx Node::QuerySum(int l,int r){
    if(l<=this->l&&this->r<=r)
        return this->sum;
    else{
        this->PushDown();
        if(r<=this->lch->r)
            return this->lch->QuerySum(l,r);
        if(this->rch->l<=l)
            return this->rch->QuerySum(l,r);
        return this->lch->QuerySum(l,r)+this->rch->QuerySum(l,r);
    }
}
 
int Node::QueryMin(int l,int r){
    if(l<=this->l&&this->r<=r)
        return this->min;
    else{
        this->PushDown();
        if(r<=this->lch->r)
            return this->lch->QueryMin(l,r);
        if(this->rch->l<=l)
            return this->rch->QueryMin(l,r);
        return std::min(this->lch->QueryMin(l,r),this->rch->QueryMin(l,r));
    }
}
 
void Node::Add(int l,int r,int d){
    if(l<=this->l&&this->r<=r)
        this->Add(d);
    else{
        this->PushDown();
        if(l<=this->lch->r)
            this->lch->Add(l,r,d);
        if(this->rch->l<=r)
            this->rch->Add(l,r,d);
        this->Maintain();
    }
}
 
void Node::Div(int l,int r,int d){
    if(l<=this->l&&this->r<=r){
        if(this->max-FDiv(this->max,d)==this->min-FDiv(this->min,d))
            this->Add(FDiv(this->max,d)-this->max);
        else{
            this->PushDown();
            this->lch->Div(l,r,d);
            this->rch->Div(l,r,d);
            this->Maintain();
        }
    }
    else{
        this->PushDown();
        if(l<=this->lch->r)
            this->lch->Div(l,r,d);
        if(this->rch->l<=r)
            this->rch->Div(l,r,d);
        this->Maintain();
    }
}
 
inline void Node::Add(int d){
    this->max+=d;
    this->min+=d;
    this->add+=d;
    this->sum+=1ll*(this->r-this->l+1)*d;
}
 
inline void Node::Maintain(){
    this->sum=this->lch->sum+this->rch->sum;
    this->max=std::max(this->lch->max,this->rch->max);
    this->min=std::min(this->lch->min,this->rch->min);
}
 
inline void Node::PushDown(){
    if(this->add!=0){
        this->lch->Add(this->add);
        this->rch->Add(this->add);
        this->add=0;
    }
}
 
Node::Node(int l,int r):l(l),r(r),max(a[l]),min(a[r]),add(0),sum(a[l]),lch(NULL),rch(NULL){
    if(l!=r){
        int mid=(l+r)>>1;
        this->lch=new Node(l,mid);
        this->rch=new Node(mid+1,r);
        this->Maintain();
    }
}
 
inline int ReadInt(){
    int x=0,sgn=1;
    register char ch=getchar();
    while(!isdigit(ch)){
        if(ch=='-')
            sgn=-sgn;
        ch=getchar();
    }
    while(isdigit(ch)){
        x=x*10+ch-'0';
        ch=getchar();
    }
    return x*sgn;
}
 
inline int FDiv(int x,int d){
    if(x>=0)
        return x/d;
    else
        return (x-d+1)/d;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值