#6029. 【雅礼集训 2017 Day1】市场

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

题目描述

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

有 n nn 个商贩,从 0∼n−1 0 \sim n - 10n1 编号,每个商贩的商品有一个价格 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_ii[l,r]​​ai​​

输入格式

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

输出格式

对于每个 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,q103​​;
对于 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\n",query_min(1,x,y));
128         else printf("%lld\n",query_sum(1,x,y));
129     }
130     return 0;
131 }
132 
133 int sb=hh();
134 int main(int argc,char**argv) {;}
代码

 

posted @ 2017-09-05 18:23  拿叉插猹哈  阅读(251)  评论(0编辑  收藏  举报