隐藏
「LibreOJ6029」「雅礼集训 2017 Day1」市场 - 区间除法线段树 | Bill Yang's Blog

路终会有尽头,但视野总能看到更远的地方。

0%

「LibreOJ6029」「雅礼集训 2017 Day1」市场 - 区间除法线段树

题目大意

    从前有一个贸易市场,在一位执政官到来之前都是非常繁荣的,自从他来了之后,发布了一系列奇怪的政令,导致贸易市场的衰落。
    有$n$个商贩,从$0 \sim n-1$编号,每个商贩的商品有一个价格$a_i$​​,有两种政令:

  1. $l,r,c$,对于$i\in[l,r],a_i\leftarrow a_i+c$
  2. $l,r,d$,对于$i\in[l,r],a_i\leftarrow\lfloor\frac{a_i}{d}\rfloor$

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

  1. 给定$l,r$,求$\min_{i\in[l,r]}a_i$​
  2. 给定$l,r$,求$\sum_{i\in[l,r]}a_i$

题目分析

线段树区间除法模板题。
update:2017/1/11,之前放的外链被原作者删了。。。放坑待填。


代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
#include<algorithm>
#include<iostream>
#include<iomanip>
#include<cstring>
#include<cstdlib>
#include<climits>
#include<vector>
#include<cstdio>
#include<cmath>
#include<queue>
using namespace std;

typedef long long LL;

inline const int Get_Int() {
int num=0,bj=1;
char x=getchar();
while(x<'0'||x>'9') {
if(x=='-')bj=-1;
x=getchar();
}
while(x>='0'&&x<='9') {
num=num*10+x-'0';
x=getchar();
}
return num*bj;
}

const int maxn=100005;

int div_down(int x,int y) {
if(x<0)return (x+1)/y-1;
return x/y;
}

struct Segment_Tree {
struct Tree {
int left,right;
int max,min,lazy;
LL sum;
Tree(int l=0,int r=0,int v=0):left(l),right(r),max(v),min(v),lazy(0),sum(v) {}
} tree[maxn<<2];
#define ls index<<1
#define rs index<<1|1
void build(int index,int Left,int Right,int* a) {
tree[index]=Tree(Left,Right);
if(Left==Right) {
tree[index]=Tree(Left,Right,a[Left]);
return;
}
int mid=(Left+Right)>>1;
build(ls,Left,mid,a);
build(rs,mid+1,Right,a);
push_up(index);
}
void push_up(int index) {
tree[index].max=max(tree[ls].max,tree[rs].max);
tree[index].min=min(tree[ls].min,tree[rs].min);
tree[index].sum=tree[ls].sum+tree[rs].sum;
}
void push_down(int index) {
if(!tree[index].lazy)return;
modify(ls,tree[index].lazy);
modify(rs,tree[index].lazy);
tree[index].lazy=0;
}
void modify(int index,LL val) {
tree[index].sum+=val*(tree[index].right-tree[index].left+1);
tree[index].lazy+=val;
tree[index].max+=val;
tree[index].min+=val;
}
void add(int index,int Left,int Right,int val) {
if(Left>tree[index].right||Right<tree[index].left)return;
if(Left<=tree[index].left&&Right>=tree[index].right) {
modify(index,val);
return;
}
push_down(index);
add(ls,Left,Right,val);
add(rs,Left,Right,val);
push_up(index);
}
void div(int index,int Left,int Right,int val) {
if(Left>tree[index].right||Right<tree[index].left)return;
if(Left<=tree[index].left&&Right>=tree[index].right) {
int delta1=tree[index].max-div_down(tree[index].max,val),delta2=tree[index].min-div_down(tree[index].min,val);
if(delta1==delta2) {
modify(index,-delta1);
return;
}
}
push_down(index);
div(ls,Left,Right,val);
div(rs,Left,Right,val);
push_up(index);
}
int query_min(int index,int Left,int Right) {
if(Left>tree[index].right||Right<tree[index].left)return INT_MAX;
if(Left<=tree[index].left&&Right>=tree[index].right)return tree[index].min;
push_down(index);
return min(query_min(ls,Left,Right),query_min(rs,Left,Right));
}
LL query_sum(int index,int Left,int Right) {
if(Left>tree[index].right||Right<tree[index].left)return 0;
if(Left<=tree[index].left&&Right>=tree[index].right)return tree[index].sum;
push_down(index);
return query_sum(ls,Left,Right)+query_sum(rs,Left,Right);
}
} st;

int n,m,a[maxn];

int main() {
n=Get_Int();
m=Get_Int();
for(int i=1; i<=n; i++)a[i]=Get_Int();
st.build(1,1,n,a);
while(m--) {
int opt=Get_Int(),l=Get_Int()+1,r=Get_Int()+1;
if(opt==1)st.add(1,l,r,Get_Int());
else if(opt==2)st.div(1,l,r,Get_Int());
else if(opt==3)printf("%d\n",st.query_min(1,l,r));
else printf("%lld\n",st.query_sum(1,l,r));
}
return 0;
}
姥爷们赏瓶冰阔落吧~