NBUT 1457 Sona

http://cdn.ac.nbutoj.com/Problem/view.xhtml?id=1457

Thinking in blocking.

The solution of  this problem shocks me a lot.

Grouping queries which it's left end in the same block which is sqrt(N) width.

Sort queries in the same group accordding to the right end, then left end.

For each group, maintain two pointers, current left bound(lb) and current right bound(rb).

As rb never decreases , for each gourp rb move N step at most.

The difference betweem lbs in a group at most sqrt(N).

And we have Q queries.

Hence, we have O((N+Q)*sqrt(N))

#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;
const int N = 1e5+10;
const int M = 512;
typedef map MII;
typedef long long LL;

struct ask_t {
  int l, r, i;
  friend bool operator < (ask_t lhs, ask_t rhs) {
    if (lhs.r == rhs.r) return lhs.l < rhs.l;
    return lhs.r < rhs.r;
  }
  void input(int _i) {
    i = _i;
    scanf("%d%d", &l, &r);
  }
};

int n, m, s[N], h[N];
LL ans[N];

int main() {
  for ( ; ~scanf("%d", &n); ) {
    MII pm;
    for (int i = 1; i <= n; i++) {
      scanf("%d", s+i);
      pm[s[i]] = 1;
    }
    int rank = 1;
    for (MII::iterator i = pm.begin(); i != pm.end(); i++)
      i->second = rank++;
    for (int i = 1; i <= n; i++) s[i] = pm[s[i]];
    scanf("%d", &m);
    vector va[M];
    for (int i = 0; i < m; i++) {
      ask_t a;
      a.input(i);
      va[a.l/M].push_back(a);
    }
    int bl = n/M+(n%M>0)+1;
    for (int i = 0; i < bl; i++) {
#define _cube(x) (1LL*x*x*x)
#define _bf(x, y) {\
      sum -= _cube(h[s[x]]);\
      h[s[x]]y;\
      sum += _cube(h[s[x]]);}
      memset(h+1, 0, sizeof(int)*n);
      sort(va[i].begin(), va[i].end());
      int lb = 1, rb = 1;
      LL sum = 0;
      for (int j = 0; j < va[i].size(); j++) {
        for ( ; rb < va[i][j].r+1; rb++) _bf(rb, ++);
        if (lb < va[i][j].l) {
          for ( ; lb < va[i][j].l; lb++) _bf(lb, --);
        } else if (lb > va[i][j].l) {
          for ( ; lb > va[i][j].l; lb--) _bf(lb-1, ++);
        }
        ans[va[i][j].i] = sum;
      }
    }
    for (int i = 0; i < m; i++) printf("%lld\n", ans[i]);
  }
  return 0;
}


你可能感兴趣的:(Blocking)