【JZOJ 1384】 Alice的游戏

题目大意:

给出一个长度为 \(N\) 的数列,\(M\) 次操作,每次操作两个数 \(a\)\(b\),且在数列中的闭区间 \([a,b]\) 中的每个数都要加一且对其模十,在此之前要求出每个数的和。

正文:

因为 \(N \leq250000\) 所以要考虑 \(O(n\log n)\) 的算法,这里用到线段树。

本题可以用线段树每个节点维护一段零至九的序列就好了,本题码量大,主要考验的是代码实现能力。

代码:

inline void opt(int x) {
    sgt[x].val = sgt[x << 1].val + sgt[x << 1 | 1].val;
    for(register int i = 0; i <= 9; ++i) {
          val[x][i] = val[x << 1][i] + val[x << 1 | 1][i];
    }
}

void build(int x, int l, int r) {
    sgt[x].l = l, sgt[x].r = r;

    if(l == r) {
          sgt[x].val = a[l];
          ++val[x][a[l]];
          return ;
    }
    int mid = (sgt[x].l + sgt[x].r) / 2;
    build(x << 1, l, mid);
    build(x << 1 | 1, mid + 1, r);
    opt(x);
}

int tool[11];

void spreadd(int x)
{
	for(int i = 0; i <= 9; i++)
	{
		tool[(i + sgt[x].dif) % 10] = val[x][i];
	}
	sgt[x].val = 0;
	for(int i = 0; i <= 9; i++)
	{
		val[x][i] = tool[i];
		sgt[x].val += val[x][i] * i;
	}
	sgt[x].dif = 0;
}

void spread(int x) {
    if(sgt[x].lzy) {
          sgt[x << 1].lzy += sgt[x].lzy;
          sgt[x << 1 | 1].lzy += sgt[x].lzy;
          sgt[x << 1].dif += sgt[x].lzy;
          sgt[x << 1 | 1].dif += sgt[x].lzy;
          sgt[x].lzy = 0;
          spreadd(x << 1);
          spreadd(x << 1 | 1);
          spreadd(x);
    }
}

int search(int x, int l, int r) {
      if(l <= sgt[x].l && sgt[x].r <= r) {
            return sgt[x].val;
      }
      spread(x);
      int mid = (sgt[x].l + sgt[x].r) / 2;
      if(mid < l) return search(x << 1 | 1, l, r);
      if(mid >= r) return search(x << 1, l, r);
      return search(x << 1, l, mid) + search(x << 1 | 1, mid + 1, r);
}

void change(int x, int l, int r)
{
      if(l == sgt[x].l && r == sgt[x].r)
      {
            sgt[x].lzy++;
            sgt[x].dif++;
            spreadd(x);
            return;
      }
      spread(x);
      int mid = (sgt[x].l + sgt[x].r) / 2;
      bool flag = 1;
      if(mid < l) change(x << 1 | 1, l, r), flag=0;
      if(mid >= r) change(x << 1, l, r), flag=0;
      if(flag) {
            change(x << 1, l, mid);
            change(x << 1 | 1, mid + 1, r);
      }
      opt(x);
}
posted @ 2020-04-26 22:23  Jayun  阅读(130)  评论(1编辑  收藏  举报