贪心 codeforces 878E

http://codeforces.com/contest/878/problem/E

tag是假的

\(ans = \sum_{i=1}^{n}a_i2^{k_i} \; \; 1 \le k_i \le k_{i-1}+1\)

如果对于\([l, r]\)是正的话从右往左加贪心

离线后从左往右加数

如果是负数那么单独成一块

否则就向前面的块合并

并查集维护一下块的答案

复杂度\(O(n\alpha (n))\)

#include<bits/stdc++.h>
#define int long long
using namespace std;

template<typename tp> inline void read(tp &x) {
  x = 0; char c = getchar(); int f = 0;
  for(; c < '0' || c > '9'; f |= c == '-', c = getchar());
  for(; c >= '0' && c <= '9'; x = (x << 3) + (x << 1) + c - '0', c = getchar());
  if(f) x = -x;
}
namespace {
  const int mo = 1e9 + 7;
  const int inv2 = (mo + 1) / 2;
  inline int add(int x, int y) {
    if((x += y) >= mo) x -= mo;
    if(x < 0) x += mo;
    return x;
  }
  inline int sub(int x, int y) {
    if((x -= y) < 0) x += mo;
    if(x >= mo) x -= mo;
    return x;
  }
  inline int mul(int x, int y) {
    return x * y % mo;
  }
  inline int pw(int a, int k, int mo) {
    int ans = 1;
    for(; k; k >>= 1, a = mul(a, a))
      if(k & 1) ans = mul(ans, a);
    return ans;
  }
}
const int N = 3e5 + 233;
const int LIM = 3e9 + 233;
struct Query {
  int l, r, id, ans;
}q[N];
vector<Query> vec[N];
int ipw2[N], pw2[N], suf[N];
int pre[N], sum[N], st[N], ed[N], su[N];
int S[N], top = 0;
int n, m, ans[N], a[N];
inline int get(int l, int r) {
  return mul(ipw2[l - 1], sub(suf[r], suf[l - 1]));
}

inline void init(void) {
  pw2[0] = 1;
  for(int i = 1; i < N; i ++)
    pw2[i] = mul(pw2[i - 1], 2);
  ipw2[0] = 1;
  for(int i = 1; i < N; i ++)
    ipw2[i] = mul(ipw2[i - 1], inv2);
  for(int i = 1; i <= n; i ++) {
    suf[i] = add(suf[i - 1], mul(a[i], pw2[i - 1]));
  }
}

inline int find(int x) {
  return pre[x] == x ? x : pre[x] = find(pre[x]);
}

inline void uni(void) {
  int fx = S[top], fy = S[top - 1];
  top -= 2;
  pre[fy] = fx;
  if(ed[fy] - st[fy] + 1 + log2(sum[fx]) >= 38) sum[fx] = LIM;
  else {
    sum[fx] <<= ed[fy] - st[fy] + 1;
    sum[fx] += sum[fy];
    if(sum[fx] >= LIM) sum[fx] = LIM;
  }
  st[fx] = st[fy];
  S[++ top] = fx;
  su[S[top]] = add(su[S[top - 1]], get(st[fx], ed[fx]));
}

inline int gao(int l) {
  int fa = find(l);
  int ans = 0;
  ans = mul(2, sub(su[S[top]], su[fa]));
  ans = add(ans, get(l, ed[fa]));
  return ans;  
}

inline void doit(void) {
  for(int i = 1; i <= n; i ++) {
    pre[i] = i, sum[i] = a[i];
    st[i] = ed[i] = i;
  }
  for(int i = 1; i <= n; i ++) {
    S[++ top] = i; 
    su[S[top]] = add(su[S[top - 1]], get(st[i], ed[i]));
    while(top >= 2 && sum[find(S[top])] >= 0) {
      uni();
    }
    for(auto t: vec[i]) {
      ans[t.id] = gao(t.l);
    }
  }
}

main(void) {
  read(n); read(m);
  for(int i = 1; i <= n; i ++) {
    read(a[i]);
  }
  init();
  for(int i = 1; i <= m; i ++) {
    read(q[i].l); read(q[i].r); q[i].id = i;
    vec[q[i].r].push_back(q[i]);
  }
  doit();
  for(int i = 1; i <= m; i ++)
    cout << ans[i] << "\n";
}

猜你喜欢

转载自www.cnblogs.com/foreverpiano/p/cf878E.html