Lucky Array CodeForces - 121E (线段树,好题)
Posted uid001
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Lucky Array CodeForces - 121E (线段树,好题)相关的知识,希望对你有一定的参考价值。
题目大意:
定义只含数字$4,7$的数字为幸运数, 给定序列, 区间加正数, 区间询问多少个幸运数
题解:
对于每一个数, 求出它和第一个比它大的幸运数之差, 则问题转化为区间加,查询$0$的个数
可以维护最大值即最大值的个数, 对于最大值$<=0$直接打标记修改即可
对于最大值$>0$的暴力转移到下一个幸运数,
因为对于每个幸运数来说, 最多有n个元素暴力修改, 可以看成n个点单点更新
所以暴力修改的复杂度$O(Cnlogn)$, $C$为总幸运数个数
总复杂度$O((n+m)logn+Cnlogn)$
1 #include <iostream> 2 #include <algorithm> 3 #include <cstdio> 4 #define REP(i,a,n) for(int i=a;i<=n;++i) 5 #define mid ((l+r)>>1) 6 #define lc (o<<1) 7 #define rc (lc|1) 8 #define ls lc,l,mid 9 #define rs rc,mid+1,r 10 using namespace std; 11 12 const int N = 4e5+10, INF = 0x3f3f3f3f; 13 int n, m, ql, qr; 14 int a[N], s[N]; 15 16 struct _ { 17 int mx, cnt, tag; 18 _ () {} 19 _ (int mx, int cnt) :mx(mx),cnt(cnt),tag(0) {} 20 _ operator + (const _ &rhs) const { 21 if (mx<rhs.mx) return _(rhs.mx,rhs.cnt); 22 if (mx>rhs.mx) return _(mx,cnt); 23 return _(mx,cnt+rhs.cnt); 24 } 25 void add(int k) { 26 mx+=k, tag+=k; 27 } 28 } v[N<<2]; 29 30 void dfs(int x) { 31 if (x>10000) return; 32 s[++*s]=x; 33 dfs(x*10+4),dfs(x*10+7); 34 } 35 36 void build(int o, int l, int r) { 37 if (l==r) { 38 int t; 39 scanf("%d", &t); 40 int id = lower_bound(s+1,s+1+*s,t)-s; 41 v[o]=_(t-s[id],1); 42 a[l]=id; 43 return; 44 } 45 build(ls),build(rs); 46 v[o]=v[lc]+v[rc]; 47 } 48 49 void pd(int o) { 50 if (v[o].tag) { 51 v[lc].add(v[o].tag); 52 v[rc].add(v[o].tag); 53 v[o].tag=0; 54 } 55 } 56 57 58 void upd(int o, int l, int r) { 59 if (v[o].mx<=0) return; 60 if (l==r) { 61 while (v[o].mx>0) { 62 v[o].mx -= s[a[l]+1]-s[a[l]]; 63 ++a[l]; 64 } 65 return; 66 } 67 pd(o),upd(ls),upd(rs); 68 v[o]=v[lc]+v[rc]; 69 } 70 71 void add(int o, int l, int r, int k) { 72 if (ql<=l&&r<=qr) return v[o].add(k),upd(o,l,r); 73 pd(o); 74 if (mid>=ql) add(ls,k); 75 if (mid<qr) add(rs,k); 76 v[o]=v[lc]+v[rc]; 77 } 78 79 _ qry(int o, int l, int r) { 80 if (ql<=l&&r<=qr) return v[o]; 81 pd(o); 82 if (mid<ql) return qry(rs); 83 if (mid>=qr) return qry(ls); 84 return qry(ls)+qry(rs); 85 } 86 87 int main() { 88 dfs(4),dfs(7); 89 sort(s+1,s+1+*s),*s=unique(s+1,s+1+*s)-s-1; 90 s[++*s]=INF; 91 scanf("%d%d", &n, &m); 92 build(1,1,n); 93 REP(i,1,m) { 94 int k; 95 char op[10]; 96 scanf("%s%d%d", op, &ql, &qr); 97 if (*op==‘a‘) scanf("%d", &k), add(1,1,n,k); 98 else { 99 _ ret = qry(1,1,n); 100 printf("%d ",ret.mx?0:ret.cnt); 101 } 102 } 103 }
以上是关于Lucky Array CodeForces - 121E (线段树,好题)的主要内容,如果未能解决你的问题,请参考以下文章
Lucky Array CodeForces - 121E (线段树,好题)