zoukankan      html  css  js  c++  java
  • 【JZOJ 1384】 Alice的游戏

    题目大意:

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

    正文:

    因为 (N leq250000) 所以要考虑 (O(nlog 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);
    }
    
  • 相关阅读:
    第十次作业
    第九次作业总结
    第九次作业
    第八次作业总结
    第七次作业总结
    第六次总结
    第十二次作业总结
    第十一次作业总结
    第十次作业总结
    第九次作业总结
  • 原文地址:https://www.cnblogs.com/GJY-JURUO/p/12782808.html
Copyright © 2011-2022 走看看