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 (线段树,好题)

CodeForces - 808A Lucky Year

CodeForces - 808A Lucky Year

『题解』Codeforces121A Lucky Sum

Lucky Numbers (easy) CodeForces - 96B

@codeforces - 1096G@ Lucky Tickets