Optimization of calculations of cycling elements



  • There is a sizeable body whose elements have a line of increation after which they turn to zero (e.g. 34, 35, 0, 1, 2 ...) and the sum of the elements between certain positions should be considered, removed, followed by these elements being encrypted, then done the same again, but between possible other positions. Accordingly, the number of transactions will be equal to the sum of all intervals of multiplied by two + checks of elements for the border crossing, which is long enough. Can this process be optimized in some way, taking into account the cyclicality of the processes?



  • The challenge is clearly olimpiad.

    The general idea is the tree of lazy operations and the balance of peaks. For simplicity, we'll record the value in MOD. It won't make it harder, but it'll make it easier.

    Yeah, there's a lot of two multipliers here can be replaced for. x+x x<<1 And as much as you like.

    Main reference- http://e-maxx.ru/algo/segment_tree

    Component structure

    struct Node{
        long sum;
        int CountV[MOD];
        int pending;
    }
    

    We'll need backup functions:

    void AddMod(int CountV[MOD], int delt){  //выполняет сдвиг массива 
         int temp[MOD];                      //(можно оптимальнее) 
         memcpy(temp,CountV,MOD*sizeof(int));
         for (int i=0;i<MOD;i++)
            CountV[(i + delt) % MOD] = temp[i];
    }
    

    void addV(int &x, int y){ //добавляет число по модулю
    x+=y;
    x%=MOD;
    }

    void relax(int U, int d){ //добавляет в вершине отложенно d
    AddMod(U, d);
    addV(Tree[U].pending, d);
    Tree[U].sum = 0;
    for (int i = 0;i<10;i++)
    Tree[U].sum += i*Tree[U].CountV[i];
    }

    void forcePush(int U){ //"пропихивает" через вершину отложенное

    relax(2*U,Tree[U].pending);
    relax(2*U + 1,Tree[U].pending);
    
    Tree[U].pending = 0;
    Tree[U].sum = 0;
    for (int i = 0;i&lt;10;i++)
        Tree[U].sum += i*(Tree[U].CountV[i] = Tree[2 * U].CountV[i] +
                                          Tree[2 * U + 1].CountV[i]);
    

    }

    We're doing a standard tree line in 1!

    void add(int U, int L, int R, int l, int r, int val) { //l,r - нужный
    if (L >= r || R <= l) return; //отрезок
    l = max(l, L);
    r = min(R, r);
    if (L == l && R == r) {
    relax(U,val);
    return;
    }
    forcePush(U);
    add(2 * U, L, (L + R) >> 1, l, r, val);
    add(2 * U + 1, (L + R) >> 1, R, l, r, val);
    forcePush(U);

    }

    long getSum(int U, int L, int R, int l, int r) {
    if (L >= r || R <= l)
    return 0;
    l = max(l, L);
    r = min(R, r);
    if (L == l && R == r)
    return Tree[U].sum;
    forcePush(U);
    long res = getSum(2 * U, L, (L + R) >> 1, l, r) +
    getSum(2 * U + 1, (L + R) >> 1, R, l, r);
    return res;
    }

    void init(int U, int L, int R){
    if (L >= R) return;
    if (L + 1 == R){
    Tree[U].CountV[ INIT[L] ] = 1;
    Tree[U].sum = INIT[L];
    return;
    }
    init(2U,L, (L + R) >> 1);
    init(2
    U+1,(L + R) >> 1,R);
    for (int i = 0;i<10;i++)
    Tree[U].sum += i*(Tree[U].CountV[i] = Tree[2 * U].CountV[i] +
    Tree[2 * U + 1].CountV[i]);
    }

    Once again, the idea is, in the top of the tree, there's a value as long as it's pushed there. When we have to count the amount, we're just pulling these values when we go downstairs pushing that value. It's like it's just that a tree is recommended to read it completely.

    Challenges - getSum(1,0,MaxN, left, rigth);

    More detailed at the request.

    In every peak, we know the ring of equal elements. i In her cut.

    Let's say that the request for an addition will be exactly for the cuts covered by the top. Then we put a mark on the top that's added and everything. If the surface isn't full, there's no choice, let's go to the left and right, we're not doing the same thing. If there's something in the top and we're going down, then we're gonna get the value down.

    Now the sum. If we come to the top, which contains exactly the cuts we need, then we can count the sum in it easily. (summa) i*Count[i])
    If not, let's go down and squeeze the value. Now that we have reached such a summit, we need to complete the deferred summarization. It's enough to cause a function. AddMod described above. I don't think you should explain what she's doing.

    Code complete http://ideone.com/1vuNAm ♪

    It can be optimized (e.g. 2 calls) forcePush(U); Total add No need. But I'll leave it as an exercise:




Suggested Topics

  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2