每日练习 2021.9.25
1. ZOJ 1610 Count the Colors
2. HDU 1698 Just a Hook
3. HDU 4027 Can you answer these queries?
4. ZOJ 3197 Google Book
1. ZOJ 1610 Count the Colors
直接线段树维护就好了,没什么好说的>__<
#include <bits/stdc++.h> #include <cstring> using namespace std; const int maxn = 8010; struct Tree { int l, r, col; #define l( p ) t[ p ].l #define r( p ) t[ p ].r #define col( p ) t[ p ].col } t[ maxn << 2 ]; int q[ maxn ], tmp; int n; inline void pushdown( int p ) { if ( col( p ) == -1 ) return; col( p << 1 ) = col( p << 1 | 1 ) = col( p ); col( p ) = -1; } void build( int p, int l, int r ) { l( p ) = l, r( p ) = r, col( p ) = -1; if ( l == r ) return; int mid = l + r >> 1; build( p << 1, l, mid ); build( p << 1 | 1, mid + 1, r ); } void update( int p, int l, int r, int c ) { if ( l <= l( p ) && r >= r( p ) ) { col( p ) = c; return; } pushdown( p ); int mid = l( p ) + r( p ) >> 1; if ( l <= mid ) update( p << 1, l, r, c ); if ( r > mid ) update( p << 1 | 1, l, r, c ); } void query( int p, int l, int r ) { if ( l == r ) { if ( col( p ) != -1 && col( p ) != tmp ) q[ col( p ) ]++; tmp = col( p ); return; } pushdown( p ); int mid = l + r >> 1; query( p << 1, l, mid ); query( p << 1 | 1, mid + 1, r ); } int main( ) { ios::sync_with_stdio( false ); cin.tie( nullptr ), cout.tie( nullptr ); while ( cin >> n ) { build( 1, 1, 8000 ); for ( int i = 1; i <= n; i++ ) { int u, v, w; cin >> u >> v >> w; update( 1, u + 1, v, w ); } tmp = -1; memset( q, 0, sizeof( q ) ); query( 1, 1, 8000 ); for ( int i = 0; i <= 8000; i++ ) if ( q[ i ] ) cout << i << ' ' << q[ i ] << '\n'; cout << '\n'; } }
2. HDU 1698 欲修改的值只有1,2,3, 直接打在lazy tag上面就可以了,求和直接求和
#include <bits/stdc++.h> using namespace std; const int maxn = 1e5 + 10; struct Tree { int l, r, add; #define l( p ) t[ p ].l #define r( p ) t[ p ].r #define add( p ) t[ p ].add } t[ maxn << 2 ]; int n, m; inline void pushdown( int p ) { if( add( p ) == -1 ) return; add( p << 1 ) = add( p << 1 | 1 ) = add( p ); add( p ) = -1; } void build( int p, int l, int r ) { l( p ) = l, r( p ) = r, add( p ) = -1; if( l == r ) return; int mid = l + r >> 1; build( p << 1, l, mid ); build( p << 1 | 1, mid + 1, r ); } void update( int p, int l, int r, int x ) { if( l <= l( p ) && r >= r( p ) ) { add( p ) = x; return; } pushdown( p ); int mid = l( p ) + r( p ) >> 1; if( l <= mid ) update( p << 1, l, r, x ); if( r > mid ) update( p << 1 | 1, l, r, x ); } int query( int p, int l, int r ) { if( l <= l( p ) && r >= r( p ) && add( p ) != -1 ) return add( p ) * ( r( p ) - l( p ) + 1 ); pushdown( p ); if( l( p ) == r( p ) ) return add( p ); int mid = l( p ) + r( p ) >> 1; int ans = 0; if( l <= mid ) ans += query( p << 1, l, r ); if( r > mid ) ans += query( p << 1 | 1, l, r ); return ans; } int main( ) { int T, kse = 1; scanf( "%d", &T ); while( T-- ) { scanf( "%d%d", &n, &m ); build( 1, 1, n ); add( 1 ) = 1; while( m-- ) { int u, v, w; scanf( "%d%d%d", &u, &v, &w ); update( 1, u, v, w ); } printf( "Case %d: The total value of the hook is %d.\n", kse++, query( 1, 1, n ) ); } return 0; }
3. HDU 4027 区间开根号,区间求和。注意到最大也就( 1 << 63 ) - 1, 至多开6次根号后必定为1,所以直接暴力修改即可,在节点上记录区间是否全为1
#include <bits/stdc++.h> using namespace std; const int maxn = 1e5 + 10; using ll = long long; ll a[ maxn ]; int n, m; struct Tree { int l, r; ll val; #define l( p ) t[ p ].l #define r( p ) t[ p ].r #define val( p ) t[ p ].val } t[ maxn << 2 ]; inline void pushup( int p ) { val( p ) = val( p << 1 ) + val( p << 1 | 1 ); } void build( int p, int l, int r ) { l( p ) = l, r( p ) = r; if( l == r ) { val( p ) = a[ l ]; return; } int mid = l + r >> 1; build( p << 1, l, mid ); build( p << 1 | 1, mid + 1, r ); pushup( p ); } void update( int p, int l, int r ) { if( val( p ) == r( p ) - l( p ) + 1 ) return; if( l( p ) == r( p ) ) { val( p ) = sqrt( val( p ) ); return; } int mid = l( p ) + r( p ) >> 1; if( l <= mid ) update( p << 1, l, r ); if( r > mid ) update( p << 1 | 1, l, r ); pushup( p ); } ll query( int p, int l, int r ) { if( l <= l( p ) && r >= r( p ) ) return val( p ); int mid = l( p ) + r( p ) >> 1; ll ans = 0; if( l <= mid ) ans += query( p << 1, l, r ); if( r > mid ) ans += query( p << 1 | 1, l, r ); return ans; } int main( ) { ios::sync_with_stdio( false ); cin.tie( nullptr ), cout.tie( nullptr ); int kse = 1, T = 0; while( cin >> n ) { cout << "Case #" << kse++ << ":\n"; for( int i = 1; i <= n; i++ ) cin >> i[ a ]; cin >> m; build( 1, 1, n ); for( int i = 1; i <= m; i++ ) { int op, a, b; cin >> op >> a >> b; if( a > b ) swap( a, b ); if( op ) { cout << query( 1, a, b ) << '\n'; } else { update( 1, a, b ); } } cout << '\n'; } return 0; }
4. ZOJ 3197 直接按照终点排序贪心就可以了,但是还是写了一个线段树dp
#include <bits/stdc++.h> using namespace std; const int maxn = 5010; int n; inline int read( ) { int x = 0; char ch = getchar( ); while( ch < '0' || ch > '9' ) ch = getchar( ); while( ch >= '0' && ch <= '9' ) x = x * 10 + ch - 48, ch = getchar( ); return x; } struct node { int l, r, v; #define l( p ) t[ p ].l #define r( p ) t[ p ].r #define v( p ) t[ p ].v } t[ maxn << 2 ]; void pushup( int p ) { v( p ) = min( v( p << 1 ), v( p << 1 | 1 ) ); } void build( int p, int l, int r ) { l( p ) = l, r( p ) = r, v( p ) = 0x3f3f3f3f; if( l == r ) return; int mid = l + r >> 1; build( p << 1, l, mid ); build( p << 1 | 1, mid + 1, r ); } void update( int p, int x, int v ) { if( l( p ) == r( p ) ) { v( p ) = min( v, v( p ) ); return; } int mid = l( p ) + r( p ) >> 1; if( x <= mid ) update( p << 1, x, v ); else update( p << 1 | 1, x, v ); pushup( p ); } int query( int p, int l, int r ) { if( l <= l( p ) && r >= r( p ) ) { return v( p ); } int mid = l( p ) + r( p ) >> 1; int ans = 0x3f3f3f3f; if( l <= mid ) ans = min( ans, query( p << 1, l, r ) ); if( r > mid ) ans = min( ans, query( p << 1 | 1, l, r ) ); return ans; } int main( ) { int T = read( ); while( T-- ) { n = read( ); build( 1, 0, n ); update( 1, 0, 0 ); for( int i = 1; i <= n; i++ ) { int x = read( ), y = read( ); if( x < 1 ) x = 1; if( y > n ) y = n; update( 1, y, 1 + query( 1, x - 1, y - 1 ) ); } printf( "%d\n", query( 1, n, n ) ); } return 0; }

浙公网安备 33010602011771号