1. 程式人生 > >Lucky Array CodeForces - 121E (線段樹,好題)

Lucky Array CodeForces - 121E (線段樹,好題)

log 正數 ons pri 數字 {} struct pac col

題目鏈接

題目大意:

定義只含數字$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\n",ret.mx?0:ret.cnt); 101 } 102 } 103 }

Lucky Array CodeForces - 121E (線段樹,好題)