#define PROBLEM "https://judge.yosupo.jp/problem/rectangle_add_point_get"
#include "template/template.hpp"
#include "segment-tree/dual-segment-tree-2d.hpp"
int main () {
int n , q ;
in ( n , q );
vector < array < int , 5 >> rects ( n );
rep ( i , 0 , n ) {
int l , d , r , u , w ;
in ( l , d , r , u , w );
rects [ i ] = { l , d , r , u , w };
}
vector < array < int , 6 >> qs ( q );
vector < pair < int , int >> points ;
rep ( i , 0 , q ) {
int t ;
in ( t );
if ( t == 0 ) {
int l , d , r , u , w ;
in ( l , d , r , u , w );
qs [ i ] = { 0 , l , d , r , u , w };
} else {
int x , y ;
in ( x , y );
qs [ i ] = { 1 , x , y , 0 , 0 , 0 };
points . push_back ({ x , y });
}
}
DualSegmentTree2D < AddMonoid < long long >> seg ( points );
for ( auto [ l , d , r , u , w ] : rects ) seg . apply ( l , r , d , u , w );
for ( auto query : qs ) {
if ( query [ 0 ] == 0 ) {
auto [ _ , l , d , r , u , w ] = query ;
seg . apply ( l , r , d , u , w );
} else {
auto [ _ , x , y , __ , ___ , ____ ] = query ;
out ( seg . get ( x , y ));
}
}
}
#line 1 "verify/segment-tree/LC_rectangle_add_point_get.dual_segment_tree_2d.test.cpp"
#define PROBLEM "https://judge.yosupo.jp/problem/rectangle_add_point_get"
#line 2 "template/template.hpp"
#include <bits/stdc++.h>
using namespace std ;
#line 2 "template/macro.hpp"
#define rep(i, a, b) for (int i = (a); i < (int)(b); i++)
#define rrep(i, a, b) for (int i = (int)(b) - 1; i >= (a); i--)
#define ALL(v) (v).begin(), (v).end()
#define UNIQUE(v) sort(ALL(v)), (v).erase(unique(ALL(v)), (v).end())
#define SZ(v) (int)v.size()
#define MIN(v) *min_element(ALL(v))
#define MAX(v) *max_element(ALL(v))
#define LB(v, x) int(lower_bound(ALL(v), (x)) - (v).begin())
#define UB(v, x) int(upper_bound(ALL(v), (x)) - (v).begin())
#define YN(b) cout << ((b) ? "YES" : "NO") << "\n";
#define Yn(b) cout << ((b) ? "Yes" : "No") << "\n";
#define yn(b) cout << ((b) ? "yes" : "no") << "\n";
#line 6 "template/template.hpp"
#line 2 "template/util.hpp"
using uint = unsigned int ;
using ll = long long int ;
using ull = unsigned long long ;
using i128 = __int128_t ;
using u128 = __uint128_t ;
template < class T >
using priority_queue_asc = priority_queue < T , vector < T > , greater < T >> ;
template < class T , class S = T >
S SUM ( const vector < T >& a ) {
return accumulate ( ALL ( a ), S ( 0 ));
}
template < class T1 , class T2 >
inline bool chmin ( T1 & a , T2 b ) {
if ( a > b ) {
a = b ;
return true ;
}
return false ;
}
template < class T1 , class T2 >
inline bool chmax ( T1 & a , T2 b ) {
if ( a < b ) {
a = b ;
return true ;
}
return false ;
}
template < class T1 , class T2 >
inline bool chmin_opt ( optional < T1 >& a , T2 b ) {
if ( ! a || a > b ) {
a = b ;
return true ;
}
return false ;
}
template < class T1 , class T2 >
inline bool chmax_opt ( optional < T1 >& a , T2 b ) {
if ( ! a || a < b ) {
a = b ;
return true ;
}
return false ;
}
template < class T >
int popcnt ( T x ) {
return __builtin_popcountll ( x );
}
template < class T >
int topbit ( T x ) {
return ( x == 0 ? - 1 : 63 - __builtin_clzll ( x ));
}
template < class T >
int lowbit ( T x ) {
return ( x == 0 ? - 1 : __builtin_ctzll ( x ));
}
#line 8 "template/template.hpp"
#line 2 "template/inout.hpp"
struct Fast {
Fast () {
cin . tie ( nullptr );
ios_base :: sync_with_stdio ( false );
cout << fixed << setprecision ( 15 );
}
} fast ;
ostream & operator << ( ostream & os , __uint128_t x ) {
char buf [ 40 ];
size_t k = 0 ;
while ( x > 0 ) buf [ k ++ ] = ( char )( x % 10 + '0' ), x /= 10 ;
if ( k == 0 ) buf [ k ++ ] = '0' ;
while ( k ) os << buf [ -- k ];
return os ;
}
ostream & operator << ( ostream & os , __int128_t x ) {
return x < 0 ? ( os << '-' << ( __uint128_t )( - x )) : ( os << ( __uint128_t ) x );
}
template < class T , size_t N >
ostream & operator << ( ostream & os , const array < T , N >& a );
template < class T1 , class T2 >
istream & operator >> ( istream & is , pair < T1 , T2 >& p ) {
return is >> p . first >> p . second ;
}
template < class T1 , class T2 >
ostream & operator << ( ostream & os , const pair < T1 , T2 >& p ) {
return os << p . first << " " << p . second ;
}
template < class T >
istream & operator >> ( istream & is , vector < T >& a ) {
for ( auto & v : a ) is >> v ;
return is ;
}
template < class T >
ostream & operator << ( ostream & os , const vector < T >& a ) {
for ( auto it = a . begin (); it != a . end ();) {
os << * it ;
if ( ++ it != a . end ()) os << " " ;
}
return os ;
}
template < class T , size_t N >
ostream & operator << ( ostream & os , const array < T , N >& a ) {
for ( auto it = a . begin (); it != a . end ();) {
os << * it ;
if ( ++ it != a . end ()) os << " " ;
}
return os ;
}
template < class T >
ostream & operator << ( ostream & os , const set < T >& st ) {
os << "{" ;
for ( auto it = st . begin (); it != st . end ();) {
os << * it ;
if ( ++ it != st . end ()) os << "," ;
}
os << "}" ;
return os ;
}
template < class T1 , class T2 >
ostream & operator << ( ostream & os , const map < T1 , T2 >& mp ) {
os << "{" ;
for ( auto it = mp . begin (); it != mp . end ();) {
os << it -> first << ":" << it -> second ;
if ( ++ it != mp . end ()) os << "," ;
}
os << "}" ;
return os ;
}
void in () {}
template < typename T , class ... U >
void in ( T & t , U & ... u ) {
cin >> t ;
in ( u ...);
}
template < class ... T >
void in_zip ( int n , T & ... t ) {
assert ( n >= 0 && (( size ( t ) >= static_cast < size_t > ( n )) && ...));
for ( int i = 0 ; i < n ; i ++ ) in ( t [ i ]...);
}
void out () { cout << " \n " ; }
template < typename T , class ... U , char sep = ' ' >
void out ( const T & t , const U & ... u ) {
cout << t ;
if ( sizeof ...( u )) cout << sep ;
out ( u ...);
}
template < class T , class U >
void out_opt ( const optional < T >& opt , const U & fallback , ostream & os = cout ) {
if ( opt . has_value ())
os << opt . value ();
else
os << fallback ;
os << " \n " ;
}
template < class T , class U >
void out_opt ( const vector < optional < T >>& vec , const U & fallback , ostream & os = cout ) {
for ( auto it = vec . begin (); it != vec . end ();) {
if (( * it ). has_value ())
os << ( * it ). value ();
else
os << fallback ;
if ( ++ it != vec . end ()) os << " " ;
}
os << " \n " ;
}
namespace IO {
template < class T , class ... U >
T read ( U && ... u ) {
T t = T ( forward < U > ( u )...);
in ( t );
return t ;
}
namespace Graph {
vector < vector < int >> unweighted ( int n , int m , bool directed = false , int offset = 1 ) {
vector < vector < int >> g ( n );
for ( int i = 0 ; i < m ; i ++ ) {
int u , v ;
cin >> u >> v ;
u -= offset , v -= offset ;
g [ u ]. push_back ( v );
if ( ! directed ) g [ v ]. push_back ( u );
}
return g ;
}
template < class T >
vector < vector < pair < int , T >>> weighted ( int n , int m , bool directed = false , int offset = 1 ) {
vector < vector < pair < int , T >>> g ( n );
for ( int i = 0 ; i < m ; i ++ ) {
int u , v ;
T w ;
cin >> u >> v >> w ;
u -= offset , v -= offset ;
g [ u ]. push_back ({ v , w });
if ( ! directed ) g [ v ]. push_back ({ u , w });
}
return g ;
}
} // namespace Graph
namespace Tree {
vector < vector < int >> unweighted ( int n , bool directed = false , int offset = 1 ) {
return Graph :: unweighted ( n , n - 1 , directed , offset );
}
template < class T >
vector < vector < pair < int , T >>> weighted ( int n , bool directed = false , int offset = 1 ) {
return Graph :: weighted < T > ( n , n - 1 , directed , offset );
}
vector < vector < int >> rooted ( int n , bool to_root = true , bool to_leaf = true , int offset = 1 ) {
vector < vector < int >> g ( n );
for ( int i = 1 ; i < n ; i ++ ) {
int p ;
cin >> p ;
p -= offset ;
if ( to_root ) g [ i ]. push_back ( p );
if ( to_leaf ) g [ p ]. push_back ( i );
}
return g ;
}
} // namespace Tree
} // namespace IO
#line 10 "template/template.hpp"
#line 2 "template/debug.hpp"
#ifdef LOCAL
#define debug 1
#define show(...) _show(0, #__VA_ARGS__, __VA_ARGS__)
#else
#define debug 0
#define show(...) true
#endif
template < class T >
void _show ( int , T ) {
cerr << '\n' ;
}
template < class T1 , class T2 , class ... T3 >
void _show ( int i , const T1 & a , const T2 & b , const T3 & ... c ) {
for (; a [ i ] != ',' && a [ i ] != '\0' ; i ++ ) cerr << a [ i ];
cerr << ":" << b << " " ;
_show ( i + 1 , a , c ...);
}
#line 2 "segment-tree/dual-segment-tree-2d.hpp"
#line 2 "algebraic-structure/util.hpp"
#ifdef __cpp_concepts
#define REQUIRES(...) requires __VA_ARGS__
#else
#define REQUIRES(...)
#endif
#line 3 "algebraic-structure/magma.hpp"
#ifdef __cpp_concepts
template < class M >
concept Magma = requires ( typename M :: value_type x , typename M :: value_type y ) {
typename M :: value_type ;
{ M :: op ( x , y ) } -> same_as < typename M :: value_type > ;
};
#endif
template < class T >
struct AddMagma {
using value_type = T ;
static T op ( T x , T y ) { return x + y ; }
};
template < class T >
struct MulMagma {
using value_type = T ;
static T op ( T x , T y ) { return x * y ; }
};
template < class T , T id >
struct MaxMagma {
using value_type = T ;
static T op ( T x , T y ) { return x > y ? x : y ; }
};
template < class T , T id >
struct MinMagma {
using value_type = T ;
static T op ( T x , T y ) { return x < y ? x : y ; }
};
#line 3 "algebraic-structure/monoid.hpp"
#ifdef __cpp_concepts
template < class M >
concept Monoid = Magma < M > && requires {
{ M :: e () } -> same_as < typename M :: value_type > ;
};
#endif
template < class T >
struct AddMonoid {
using value_type = T ;
static T op ( T x , T y ) { return x + y ; }
static T e () { return T ( 0 ); }
};
template < class T >
struct MulMonoid {
using value_type = T ;
static T op ( T x , T y ) { return x * y ; }
static T e () { return T ( 1 ); }
};
template < class T , T id >
struct MaxMonoid {
using value_type = T ;
static T op ( T x , T y ) { return x > y ? x : y ; }
static T e () { return id ; }
};
template < class T , T id >
struct MinMonoid {
using value_type = T ;
static T op ( T x , T y ) { return x < y ? x : y ; }
static T e () { return id ; }
};
#line 3 "segment-tree/dual-segment-tree.hpp"
template < class M >
REQUIRES ( Monoid < M > )
struct DualSegmentTree {
using F = typename M :: value_type ;
private:
int _n , size , log ;
vector < F > lz ;
public:
DualSegmentTree () : DualSegmentTree ( 0 ) {}
explicit DualSegmentTree ( int n ) : DualSegmentTree ( vector < F > ( n , M :: e ())) {}
explicit DualSegmentTree ( const vector < F > & v ) : _n ( int ( v . size ())) {
size = 1 , log = 0 ;
while ( size < _n ) size <<= 1 , log ++ ;
lz = vector < F > ( 2 * size , M :: e ());
for ( int i = 0 ; i < _n ; i ++ ) lz [ size + i ] = v [ i ];
}
void set ( int p , F f ) {
assert ( 0 <= p && p < _n );
p += size ;
for ( int i = log ; i > 0 ; i -- ) push ( p >> i );
lz [ p ] = f ;
}
F get ( int p ) {
assert ( 0 <= p && p < _n );
p += size ;
for ( int i = log ; i > 0 ; i -- ) push ( p >> i );
return lz [ p ];
}
vector < F > all_get () {
for ( int i = 1 ; i < size ; i ++ ) push ( i );
return vector < F > ( lz . begin () + size , lz . begin () + ( size + _n ));
}
void apply ( int p , F f ) {
assert ( 0 <= p && p < _n );
p += size ;
for ( int i = log ; i > 0 ; i -- ) push ( p >> i );
inner_apply ( p , f );
}
void apply ( int l , int r , F f ) {
if ( l >= r ) return ;
assert ( 0 <= l && l <= r && r <= _n );
l += size , r += size ;
for ( int i = log ; i > 0 ; i -- ) {
if ((( l >> i ) << i ) != l ) push ( l >> i );
if ((( r >> i ) << i ) != r ) push (( r - 1 ) >> i );
}
while ( l < r ) {
if (( l & 1 ) != 0 ) inner_apply ( l ++ , f );
if (( r & 1 ) != 0 ) inner_apply ( -- r , f );
l >>= 1 , r >>= 1 ;
}
}
private:
void push ( int k ) {
inner_apply ( 2 * k , lz [ k ]);
inner_apply ( 2 * k + 1 , lz [ k ]);
lz [ k ] = M :: e ();
}
void inner_apply ( int k , F f ) { lz [ k ] = M :: op ( f , lz [ k ]); }
};
/**
* @brief Dual Segment Tree
* @docs docs/segment-tree/dual-segment-tree.md
*/
#line 4 "segment-tree/dual-segment-tree-2d.hpp"
// M: commutative monoid
template < class M >
REQUIRES ( Monoid < M > )
struct DualSegmentTree2D {
using F = typename M :: value_type ;
DualSegmentTree2D () : n ( 0 ), size ( 1 ) {}
explicit DualSegmentTree2D ( const vector < pair < int , int >>& points ) { build ( points ); }
void build ( vector < pair < int , int >> points ) {
sort ( points . begin (), points . end ());
points . erase ( unique ( points . begin (), points . end ()), points . end ());
ps = points ;
xs . clear ();
xs . reserve ( ps . size ());
for ( auto [ x , _ ] : ps ) xs . push_back ( x );
xs . erase ( unique ( xs . begin (), xs . end ()), xs . end ());
n = xs . size ();
size = 1 ;
while ( size < n ) size <<= 1 ;
ys . assign ( 2 * size , {});
seg . assign ( 2 * size , {});
for ( auto [ x , y ] : ps ) {
int k = lower_bound ( xs . begin (), xs . end (), x ) - xs . begin ();
for ( k += size ; k > 0 ; k >>= 1 ) ys [ k ]. push_back ( y );
}
for ( int k = 1 ; k < 2 * size ; k ++ ) {
sort ( ys [ k ]. begin (), ys [ k ]. end ());
ys [ k ]. erase ( unique ( ys [ k ]. begin (), ys [ k ]. end ()), ys [ k ]. end ());
seg [ k ] = DualSegmentTree < M > (( int ) ys [ k ]. size ());
}
}
bool contains ( int x , int y ) const {
auto it = lower_bound ( ps . begin (), ps . end (), make_pair ( x , y ));
return it != ps . end () && * it == make_pair ( x , y );
}
void apply ( int xl , int xr , int yl , int yr , F f ) {
if ( xl >= xr || yl >= yr ) return ;
int l = lower_bound ( xs . begin (), xs . end (), xl ) - xs . begin ();
int r = lower_bound ( xs . begin (), xs . end (), xr ) - xs . begin ();
for ( l += size , r += size ; l < r ; l >>= 1 , r >>= 1 ) {
if ( l & 1 ) apply_node ( l ++ , yl , yr , f );
if ( r & 1 ) apply_node ( -- r , yl , yr , f );
}
}
F get ( int x , int y ) {
int k = leaf ( x , y );
F ret = M :: e ();
while ( k > 0 ) {
ret = M :: op ( get_node ( k , y ), ret );
k >>= 1 ;
}
return ret ;
}
int size_x () const { return n ; }
int size_points () const { return ps . size (); }
private:
int n , size ;
vector < pair < int , int >> ps ;
vector < int > xs ;
vector < vector < int >> ys ;
vector < DualSegmentTree < M >> seg ;
int leaf ( int x , int y ) const {
auto it = lower_bound ( ps . begin (), ps . end (), make_pair ( x , y ));
assert ( it != ps . end () && * it == make_pair ( x , y ));
int k = lower_bound ( xs . begin (), xs . end (), x ) - xs . begin ();
return k + size ;
}
void apply_node ( int k , int yl , int yr , F f ) {
int l = lower_bound ( ys [ k ]. begin (), ys [ k ]. end (), yl ) - ys [ k ]. begin ();
int r = lower_bound ( ys [ k ]. begin (), ys [ k ]. end (), yr ) - ys [ k ]. begin ();
seg [ k ]. apply ( l , r , f );
}
F get_node ( int k , int y ) {
int i = lower_bound ( ys [ k ]. begin (), ys [ k ]. end (), y ) - ys [ k ]. begin ();
assert ( i < ( int ) ys [ k ]. size () && ys [ k ][ i ] == y );
return seg [ k ]. get ( i );
}
};
/**
* @brief 2D Dual Segment Tree
* @docs docs/segment-tree/dual-segment-tree-2d.md
*/
#line 5 "verify/segment-tree/LC_rectangle_add_point_get.dual_segment_tree_2d.test.cpp"
int main () {
int n , q ;
in ( n , q );
vector < array < int , 5 >> rects ( n );
rep ( i , 0 , n ) {
int l , d , r , u , w ;
in ( l , d , r , u , w );
rects [ i ] = { l , d , r , u , w };
}
vector < array < int , 6 >> qs ( q );
vector < pair < int , int >> points ;
rep ( i , 0 , q ) {
int t ;
in ( t );
if ( t == 0 ) {
int l , d , r , u , w ;
in ( l , d , r , u , w );
qs [ i ] = { 0 , l , d , r , u , w };
} else {
int x , y ;
in ( x , y );
qs [ i ] = { 1 , x , y , 0 , 0 , 0 };
points . push_back ({ x , y });
}
}
DualSegmentTree2D < AddMonoid < long long >> seg ( points );
for ( auto [ l , d , r , u , w ] : rects ) seg . apply ( l , r , d , u , w );
for ( auto query : qs ) {
if ( query [ 0 ] == 0 ) {
auto [ _ , l , d , r , u , w ] = query ;
seg . apply ( l , r , d , u , w );
} else {
auto [ _ , x , y , __ , ___ , ____ ] = query ;
out ( seg . get ( x , y ));
}
}
}