#6029. 「雅礼集训 2017 Day1」市场
题目描述
从前有一个贸易市场,在一位执政官到来之前都是非常繁荣的,自从他来了之后,发布了一系列奇怪的政令,导致贸易市场的衰落。
有 n nn 个商贩,从 0∼n−1 0 sim n - 10∼n−1 编号,每个商贩的商品有一个价格 ai a_iai,有两种政令:
- 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
- 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} floori∈[l,r],ai←⌊ai/d⌋
现在有一个外乡的旅客想要了解贸易市场的信息,有两种询问方式:
- 给定 l,r l, rl,r,求 mini∈[l,r]ai min_{i in [l, r]} a_imini∈[l,r]ai
- 给定 l,r l, rl,r,求 ∑i∈[l,r]ai sum_{iin [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≤10^5,0≤l≤r≤n−1,ci∈[−10^4,10^4],d∈[2,10^9]
线段树裸题
一开始没想到怎么处理区间除
区间除就是把它转化成区间减
需要减去的数肯定不同
但是可以考虑到一点就是如果某一段需要减去的数字是一样的
那就可以用区间更新的方法更新这一段
从而对整段[l,r]进行更新
所以对于某一段[l,r] 判断这一段是否可以减去同一个数字的方法就是看这一段区间的最大值max和最小值min需要减去多少
如果max和min需要减去的数字是一样大的
那么说明这一段都可以减去这个数字
标记下放也要把最大最小值更新
1 #include <cctype> 2 #include <cstdio> 3 4 typedef long long LL; 5 6 const int MAXN=100010; 7 8 int n,m; 9 10 struct SegmentTree { 11 int l,r; 12 LL tag; 13 LL mn,sum,mx; 14 }; 15 SegmentTree t[MAXN<<2]; 16 17 inline void read(int&x) { 18 int f=1;register char c=getchar(); 19 for(x=0;!isdigit(c);c=='-'&&(f=-1),c=getchar()); 20 for(;isdigit(c);x=x*10+c-48,c=getchar()); 21 x=x*f; 22 } 23 24 inline LL min(LL a,LL b) {return a<b?a:b;} 25 26 inline LL max(LL a,LL b) {return a<b?b:a;} 27 28 void build_tree(int now,int l,int r) { 29 t[now].l=l;t[now].r=r; 30 if(l==r) { 31 int x;read(x); 32 t[now].mx=t[now].mn=x; 33 t[now].sum=x; 34 return; 35 } 36 int mid=(l+r)>>1; 37 build_tree(now<<1,l,mid); 38 build_tree(now<<1|1,mid+1,r); 39 t[now].mn=min(t[now<<1].mn,t[now<<1|1].mn); 40 t[now].mx=max(t[now<<1].mx,t[now<<1|1].mx); 41 t[now].sum=t[now<<1].sum+t[now<<1|1].sum; 42 } 43 44 inline void down(int now) { 45 t[now<<1].tag+=t[now].tag; 46 t[now<<1].mn+=t[now].tag;t[now<<1].mx+=t[now].tag; 47 t[now<<1|1].tag+=t[now].tag; 48 t[now<<1|1].mn+=t[now].tag;t[now<<1|1].mx+=t[now].tag; 49 t[now<<1].sum+=(t[now<<1].r-t[now<<1].l+1)*t[now].tag; 50 t[now<<1|1].sum+=(t[now<<1|1].r-t[now<<1|1].l+1)*t[now].tag; 51 t[now].tag=0; 52 } 53 54 void tree_add(int now,int l,int r,int v) { 55 if(l<=t[now].l&&r>=t[now].r) { 56 t[now].mx+=v;t[now].mn+=v; 57 t[now].sum+=(t[now].r-t[now].l+1)*v; 58 t[now].tag+=v; 59 return; 60 } 61 if(t[now].tag) down(now); 62 int mid=(t[now].l+t[now].r)>>1; 63 if(l<=mid) tree_add(now<<1,l,r,v); 64 if(r>mid) tree_add(now<<1|1,l,r,v); 65 t[now].mn=min(t[now<<1].mn,t[now<<1|1].mn); 66 t[now].mx=max(t[now<<1].mx,t[now<<1|1].mx); 67 t[now].sum=t[now<<1].sum+t[now<<1|1].sum; 68 } 69 70 void tree_div(int now,int l,int r,int v) { 71 if(l<=t[now].l&&r>=t[now].r) { 72 LL _x,_y; 73 if(t[now].mn>=0) _x=t[now].mn/v;else _x=(t[now].mn-v+1)/v; 74 if(t[now].mx>=0) _y=t[now].mx/v;else _y=(t[now].mx-v+1)/v; 75 if(_x-t[now].mn==_y-t[now].mx) { 76 t[now].sum+=(t[now].r-t[now].l+1)*(_x-t[now].mn); 77 t[now].tag+=_x-t[now].mn; 78 t[now].mx+=_x-t[now].mn; 79 t[now].mn+=_x-t[now].mn; 80 return; 81 } 82 } 83 if(t[now].tag) down(now); 84 int mid=(t[now].l+t[now].r)>>1; 85 if(l<=mid) tree_div(now<<1,l,r,v); 86 if(r>mid) tree_div(now<<1|1,l,r,v); 87 t[now].mn=min(t[now<<1].mn,t[now<<1|1].mn); 88 t[now].mx=max(t[now<<1].mx,t[now<<1|1].mx); 89 t[now].sum=t[now<<1].sum+t[now<<1|1].sum; 90 } 91 92 LL query_min(int now,int l,int r) { 93 if(l<=t[now].l&&r>=t[now].r) return t[now].mn; 94 if(t[now].tag) down(now); 95 LL ans=1e17; 96 int mid=(t[now].r+t[now].l)>>1; 97 if(l<=mid) ans=min(ans,query_min(now<<1,l,r)); 98 if(r>mid) ans=min(ans,query_min(now<<1|1,l,r)); 99 return ans; 100 } 101 102 LL query_sum(int now,int l,int r) { 103 if(l<=t[now].l&&r>=t[now].r) return t[now].sum; 104 if(t[now].tag) down(now); 105 LL ans=0; 106 int mid=(t[now].l+t[now].r)>>1; 107 if(l<=mid) ans+=query_sum(now<<1,l,r); 108 if(r>mid) ans+=query_sum(now<<1|1,l,r); 109 return ans; 110 } 111 112 int hh() { 113 int x,y,type,v; 114 read(n);read(m); 115 build_tree(1,1,n); 116 for(int i=1;i<=m;++i) { 117 read(type);read(x);read(y); 118 ++x;++y; 119 if(type==1) { 120 read(v); 121 tree_add(1,x,y,v); 122 } 123 else if(type==2) { 124 read(v); 125 tree_div(1,x,y,v); 126 } 127 else if(type==3) printf("%lld ",query_min(1,x,y)); 128 else printf("%lld ",query_sum(1,x,y)); 129 } 130 return 0; 131 } 132 133 int sb=hh(); 134 int main(int argc,char**argv) {;}