每日练习 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;
}

 

posted @ 2021-09-25 16:51  Vinicilia  阅读(30)  评论(0)    收藏  举报