Submission #332590

#TimeUsernameProblemLanguageResultExecution timeMemory
332590LawlietGaraža (COCI17_garaza)C++17
160 / 160
798 ms7336 KiB
#include <bits/stdc++.h> using namespace std; typedef long long int lli; typedef pair<int,int> pii; const int MAXN = 100010; int myGCD(int a, int b) { while( b != 0 ) swap( a , b ), b %= a; return a; } class SegmentTreeOpts { public: int getLeft(int node) { return 2*node; } int getRight(int node) { return 2*node + 1; } void merge(int node, int idLeft, int idRight) { sum[node] = sum[idLeft] + sum[idRight]; mx[node] = max( mx[idLeft] , mx[idRight] ); } void refresh(int node, int l, int r) { if( lazy[node] == -1 ) return; lli lz = lazy[node]; lazy[node] = -1; mx[node] = lz; sum[node] = lz*(r - l + 1); if( l == r ) return; lazy[ getLeft(node) ] = lz; lazy[ getRight(node) ] = lz; } void build(int node, int l, int r) { lazy[node] = -1; if( l == r ) { mx[node] = sum[node] = l; return; } int m = ( l + r )/2; build( getLeft(node) , l , m ); build( getRight(node) , m + 1 , r ); merge( node , getLeft(node) , getRight(node) ); } void updateSet(int node, int l, int r, int i, int j, int v) { refresh( node , l , r ); if( j < l || r < i ) return; if( i <= l && r <= j ) { lazy[node] = v; refresh( node , l , r ); return; } int m = ( l + r )/2; updateSet( getLeft(node) , l , m , i , j , v ); updateSet( getRight(node) , m + 1 , r , i , j , v ); merge( node , getLeft(node) , getRight(node) ); } int bs(int node, int l, int r, int k) { refresh( node , l , r ); if( mx[node] < k ) return r + 1; if( l == r ) return l; int m = ( l + r )/2; refresh( getLeft(node) , l , m ); if( mx[ getLeft(node) ] >= k ) return bs( getLeft(node) , l , m , k ); return bs( getRight(node) , m + 1 , r , k ); } lli querySum(int node, int l, int r, int i, int j) { refresh( node , l , r ); if( j < l || r < i ) return 0; if( i <= l && r <= j ) return sum[node]; int m = ( l + r )/2; lli sumLeft = querySum( getLeft(node) , l , m , i , j ); lli sumRight = querySum( getRight(node) , m + 1 , r , i , j ); return sumLeft + sumRight; } protected: int mx[4*MAXN]; int lazy[4*MAXN]; lli sum[4*MAXN]; }; class SegmentTreeGCD { public: int getLeft(int node) { return 2*node; } int getRight(int node) { return 2*node + 1; } void getNodes(int node, int l, int r, int i, int j); void updateSet(int node, int l, int r, int i, int v) { if( i < l || r < i ) return; if( l == r ) { mdc[node] = v; return; } int m = ( l + r )/2; updateSet( getLeft(node) , l , m , i , v ); updateSet( getRight(node) , m + 1 , r , i , v ); mdc[node] = myGCD( mdc[ getLeft(node) ] , mdc[ getRight(node) ] ); } int bsMultiple(int node, int l, int r, int k) { if( l == r ) return l; int m = ( l + r )/2; int valRight = mdc[ getRight(node) ]; if( valRight%k == 0 ) return bsMultiple( getLeft(node) , l , m , k ); return bsMultiple( getRight(node) , m + 1 , r , k ); } int bsCoprime(int node, int l, int r, int k) { if( l == r ) return l; int m = ( l + r )/2; int valLeft = mdc[ getLeft(node) ]; int newValue = myGCD( valLeft , k ); if( newValue == 1 ) return bsCoprime( getLeft(node) , l , m , k ); return bsCoprime( getRight(node) , m + 1 , r , newValue ); } int getMDC(int node) { return mdc[node]; } SegmentTreeGCD() { for(int i = 0 ; i < 4*MAXN ; i++) mdc[i] = 1; } protected: int mdc[4*MAXN]; }; int n, q; int v[MAXN]; vector<pii> intervals; vector<int> intervalNodes; vector< pair<pii,int> > breaks; SegmentTreeGCD vGCD; SegmentTreeOpts opts; void SegmentTreeGCD::getNodes(int node, int l, int r, int i, int j) { if( j < l || r < i ) return; if( i <= l && r <= j ) { intervalNodes.push_back( node ); intervals.push_back( { l , r } ); return; } int m = ( l + r )/2; getNodes( getLeft(node) , l , m , i , j ); getNodes( getRight(node) , m + 1 , r , i , j ); } void getNodes(int L, int R) { intervals.clear(); intervalNodes.clear(); vGCD.getNodes( 1 , 1 , n , L , R ); } int findOpt(int ind, int curVal) { for(int i = 0 ; i < (int)intervalNodes.size() ; i++) { int node = intervalNodes[i]; int curG = vGCD.getMDC(node); if( myGCD( curVal , curG ) == 1 ) { int L = intervals[i].first; int R = intervals[i].second; return vGCD.bsCoprime( node , L , R , curVal ); } curVal = myGCD( curVal , curG ); } return n + 1; } void update(int ind, int val) { v[ind] = val; vGCD.updateSet( 1 , 1 , n , ind , val ); getNodes( 1 , ind ); int last = ind + 1; int curVal = v[ind]; breaks.clear(); for(int i = (int)intervals.size() - 1 ; i >= 0 ; i--) { int node = intervalNodes[i]; int curG = vGCD.getMDC(node); if( curG%curVal != 0 ) { int L = intervals[i].first; int R = intervals[i].second; int p = vGCD.bsMultiple( node , L , R , curVal ) + 1; breaks.push_back( { {p , last - 1} , curVal } ); last = p; i++; curVal = myGCD( curVal , v[p - 1] ); } } if( last != 1 ) breaks.push_back( { {1 , last - 1} , curVal } ); getNodes( ind , n ); for(int i = 0 ; i < (int)breaks.size() ; i++) { int valBreak = breaks[i].second; if( valBreak == 1 ) continue; int Lbreak = breaks[i].first.first; int Rbreak = breaks[i].first.second; int optBreak = findOpt( ind , valBreak ); opts.updateSet( 1 , 1 , n , Lbreak , Rbreak , optBreak ); } if( breaks.empty() || breaks.back().second != 1 ) return; int getFirst = opts.bs( 1 , 1 , n , ind + 1 ); int R = breaks.back().first.second; if( getFirst <= R ) opts.updateSet( 1 , 1 , n , getFirst , R , ind ); } lli getSumPA(int L, int R) { lli sz = R - L + 1; lli sum = L + R; return ( sz*sum )/2; } lli query(int L, int R) { lli ans = -getSumPA( L , R ); int last = opts.bs( 1 , 1 , n , R + 1 ); if( L <= last - 1 ) ans += opts.querySum( 1 , 1 , n , L , last - 1 ); if( last <= R ) { lli diff = R - max( L , last ) + 1; ans += diff*(R + 1); } return ans; } int main() { scanf("%d %d",&n,&q); opts.build( 1 , 1 , n ); for(int i = 1 ; i <= n ; i++) { int val; scanf("%d",&val); update( i , val ); } for(int i = 1 ; i <= q ; i++) { int type; scanf("%d",&type); if( type == 1 ) { int ind, val; scanf("%d %d",&ind,&val); update( ind , val ); } if( type == 2 ) { int L, R; scanf("%d %d",&L,&R); printf("%lld\n",query( L , R )); } } }

Compilation message (stderr)

garaza.cpp: In function 'int main()':
garaza.cpp:333:7: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
  333 |  scanf("%d %d",&n,&q);
      |  ~~~~~^~~~~~~~~~~~~~~
garaza.cpp:340:8: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
  340 |   scanf("%d",&val);
      |   ~~~~~^~~~~~~~~~~
garaza.cpp:348:8: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
  348 |   scanf("%d",&type);
      |   ~~~~~^~~~~~~~~~~~
garaza.cpp:353:9: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
  353 |    scanf("%d %d",&ind,&val);
      |    ~~~~~^~~~~~~~~~~~~~~~~~~
garaza.cpp:360:9: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
  360 |    scanf("%d %d",&L,&R);
      |    ~~~~~^~~~~~~~~~~~~~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...