Submission #498659

#TimeUsernameProblemLanguageResultExecution timeMemory
498659model_codeWeirdtree (RMI21_weirdtree)C++17
100 / 100
602 ms41140 KiB
// weirdtree_100_george.cpp

#include <bits/stdc++.h>
#include "weirdtree.h"

using namespace std;

class SegmentTree{
public:
  struct node_t{
    int max1;
    int max2;
    int cntMax;
    long long sum;
    int lazy;

    node_t(){
      this->max1 = 0;
      this->max2 = 0;
      this->cntMax = 0;
      this->sum = 0;
      this->lazy = 0;
    }

    node_t(int val){
      this->max1 = val;
      this->max2 = 0;
      this->cntMax = 1;
      this->sum = val;
      this->lazy = 0;
    }

    node_t operator + (const node_t &other)const{
      node_t ans;

      ans.sum = (this->sum + other.sum);
      ans.lazy = 0;
    
      if(this->max1 == other.max1){
        ans.max1 = this->max1;
        ans.cntMax = this->cntMax + other.cntMax;
        ans.max2 = max(this->max2,other.max2);
      }else if(this->max1 > other.max1){
        ans.max1 = this->max1;
        ans.cntMax = this->cntMax;
        ans.max2 = max(this->max2,other.max1);
      }else{
        ans.max1 = other.max1;
        ans.cntMax = other.cntMax;
        ans.max2 = max(this->max1,other.max2);
      }
    
      return ans;
    }

    void propagate(int lazy){
      this->max1 -= lazy;
      this->sum -= 1LL * lazy * this->cntMax;
      this->lazy += lazy;
    }

  };

private:
  int n;
  vector<node_t> aint;

  void build(int nod,int st,int dr,int v[]){
    if(st == dr){
      aint[nod] = node_t(v[st]);
      return ;
    }

    int mid = (st + dr) / 2;

    build(nod * 2,st,mid,v);
    build(nod * 2 + 1,mid + 1,dr,v);

    aint[nod] = aint[nod * 2] + aint[nod * 2 + 1];
  }

  void propagate(int nod,int st,int dr){
    if(aint[nod].lazy == 0 || st == dr){
      return ;
    }
    int tmpMax = max(aint[nod * 2].max1,aint[nod * 2 + 1].max1);
    if(aint[nod * 2].max1 == tmpMax){
      aint[nod * 2].propagate(aint[nod].lazy);
    }
    if(aint[nod * 2 + 1].max1 == tmpMax){
      aint[nod * 2 + 1].propagate(aint[nod].lazy);
    }

    aint[nod].lazy = 0;
  }
  

  void updateSet(int nod,int st,int dr,int pos,int value){
    propagate(nod,st,dr);

    if(dr < pos || st > pos){
      return ;
    }
    if(st == dr){
      aint[nod] = node_t(value);
      return ;
    }

    int mid = (st + dr) / 2;

    updateSet(nod * 2,st,mid,pos,value);
    updateSet(nod * 2 + 1,mid + 1,dr,pos,value);

    aint[nod] = aint[nod * 2] + aint[nod * 2 + 1];
  }

  void updateSubtract(int nod,int st,int dr,int l,int r,int value,int &bonus,int maxValue){
    propagate(nod,st,dr);
    if(value + (bonus > 0) == 0 || dr < l || st > r || (l <= st && dr <= r && aint[nod].max1 != maxValue)){
      return ;
    }
    if(l <= st && dr <= r && (bonus == 0 || bonus >= dr - st + 1) && (aint[nod].max2 == 0 || aint[nod].max1 - value - (bonus > 0) > aint[nod].max2)){
      aint[nod].propagate(value + (bonus > 0));
      bonus -= (bonus > 0) * aint[nod].cntMax;
      return ;
    }
    int mid = (st + dr) / 2;
 
    updateSubtract(nod * 2,st,mid,l,r,value,bonus,maxValue);
    updateSubtract(nod * 2 + 1,mid + 1,dr,l,r,value,bonus,maxValue);

    aint[nod] = aint[nod * 2] + aint[nod * 2 + 1];
  }

  node_t query(int nod,int st,int dr,int l,int r){
    propagate(nod,st,dr);
    if(dr < l || st > r){
      return node_t();
    }

    if(l <= st && dr <= r){
      return aint[nod];
    }

    int mid = (st + dr) / 2;

    return query(nod * 2,st,mid,l,r) + query(nod * 2 + 1,mid + 1,dr,l,r);
  }
  

public:

  SegmentTree(){
    ;
  }

  SegmentTree(int n,int v[]){
    this->n = n;
    this->aint = vector<node_t>(4 * n + 5, node_t());
    build(1,1,n,v);
  }
  
  node_t query(int st,int dr){
    return this->query(1,1,n,st,dr);
  }

  void updateSet(int pos,int value){
    this->updateSet(1,1,n,pos,value);
  }

  void updateSubtract(int l,int r,int k,int bonus,int maxValue){
    this->updateSubtract(1,1,n,l,r,k,bonus,maxValue);
  }
};

SegmentTree aint;

void initialise(int n,int q,int v[]){
  aint = SegmentTree(n, v);
}

void cut(int l,int r,int k){
  while(k > 0){
    SegmentTree::node_t tmp = aint.query(l,r);
    if(tmp.max1 == 0){
      break;
    }
    if((tmp.max1 - tmp.max2) <= k / tmp.cntMax){
      k -= (tmp.max1 - tmp.max2) * tmp.cntMax;
      aint.updateSubtract(l,r,tmp.max1 - tmp.max2,0,tmp.max1);
    }else{
      int divResult = k / tmp.cntMax;
      aint.updateSubtract(l,r,divResult,k - divResult * tmp.cntMax,tmp.max1);
      k = 0;
    }
  }
}

void magic(int i,int x){
  aint.updateSet(i,x);
}

long long inspect(int l,int r){
  return aint.query(l,r).sum;
}

#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...