传送门:【HDU】5140 Hun Gui Wei Company
题目分析:一般情况下,区间很大的话,第一反应就是离散,我也不例外,但是本题的区间很大!并且重要的是强制在线让人不能离散!但是这样就能阻挡我们AC的步伐吗?当然不能!注意到,我们将数从小到大排好序,将此时的下标作为主席树的下标,然后我们怎么为那么大的查询范围找到对应的区间呢?显然可以用二分啊~直接二分出查询的区间就好辣,因为此时数组有序满足二分的性质。
这个就是本题的技术难题。
而每次在(x,y)点插入一个权值为c的点,查询矩阵【x1,x2】【y1,y2】内所有点的权值和我们可以用主席树来做,即在下标为x的主席树上下标为y的位置插入点,查询下标【x1,x2】内主席树上【y1,y2】区间内点的和,这个比较基础,我就不熬述了。
PS:
1.注意处理好左右两边界。
2.注意数组大小。
3.区间是先加上或减去ans,然后如果左端点大于右端点就交换。
代码如下:
#include <cstdio> #include <cstring> #include <algorithm> using namespace std ; typedef long long LL ; #define rep( i , a , b ) for ( int i = ( a ) ; i < ( b ) ; ++ i ) #define For( i , a , b ) for ( int i = ( a ) ; i <= ( b ) ; ++ i ) #define rev( i , a , b ) for ( int i = ( a ) ; i >= ( b ) ; -- i ) #define clr( a , x ) memset ( a , x , sizeof a ) #define ls ( o << 1 ) #define rs ( o << 1 | 1 ) #define lson ls , l , m #define rson rs , m + 1 , r #define mid ( ( l + r ) >> 1 ) const int MAXN = 100005 ; struct Node { Node* c[2] ; LL sum ; } ; struct People { int s , l , a ; People () {} People ( int s , int l , int a ) : s ( s ) , l ( l ) , a ( a ) {} bool operator < ( const People& t ) const { return l < t.l ; } } ; People p[MAXN] ; Node pool[MAXN * 40] ; Node* cur ; Node* root[MAXN] ; int a[MAXN] ; int b[MAXN] , cnt ; int n , m ; int unique ( int n ) { int cnt = 1 ; sort ( b + 1 , b + n + 1 ) ; For ( i , 2 , n ) if ( b[i] != b[cnt] ) b[++ cnt] = b[i] ; return cnt ; } int hash ( int x , int l = 1 , int r = cnt ) { while ( l < r ) { int m = mid ; if ( b[m] >= x ) r = m ; else l = m + 1 ; } return l ; } int lower_bound ( int x , int a[] , int l , int r ) { while ( l < r ) { int m = ( l + r ) >> 1 ; if ( a[m] >= x ) r = m ; else l = m + 1 ; } return l ; } int upper_bound ( int x , int a[] , int l , int r ) { while ( l < r ) { int m = ( l + r + 1 ) >> 1 ; if ( a[m] <= x ) l = m ; else r = m - 1 ; } return r ; } void build ( Node* &o , int l , int r ) { o = cur ++ ; o->sum = 0 ; if ( l == r ) return ; int m = mid ; build ( o->c[0] , l , m ) ; build ( o->c[1] , m + 1 , r ) ; } void insert ( Node* old , Node* &now , int x , int v , int l , int r ) { now = cur ++ ; if ( l == r ) { now->sum = old->sum + v ; return ; } int m = mid ; if ( x <= m ) { now->c[1] = old->c[1] ; insert ( old->c[0] , now->c[0] , x , v , l , m ) ; } else { now->c[0] = old->c[0] ; insert ( old->c[1] , now->c[1] , x , v , m + 1 , r ) ; } now->sum = now->c[0]->sum + now->c[1]->sum ; } LL query ( Node* old , Node* now , int x , int l , int r ) { LL ans = 0 ; while ( l < r ) { int m = mid ; if ( x <= m ) { r = m ; old = old->c[0] ; now = now->c[0] ; } else { ans += now->c[0]->sum - old->c[0]->sum ; old = old->c[1] ; now = now->c[1] ; l = m + 1 ; } } ans += now->sum - old->sum ; return ans ; } void scanf ( int& x , char c = 0 ) { while ( ( c = getchar () ) < '0' ) ; x = c - '0' ; while ( ( c = getchar () ) >= '0' ) x = x * 10 + c - '0' ; } void scanf ( LL& x , char c = 0 , bool flag = 0 ) { while ( ( c = getchar () ) != '-' && c < '0' ) ; if ( c == '-' ) x = 0 , flag = 1 ; else x = c - '0' ; while ( ( c = getchar () ) >= '0' ) x = x * 10 + c - '0' ; if ( flag ) x = -x ; } void solve () { LL ll , hl , la , ha ; LL ans = 0 ; cur = pool ; For ( i , 1 , n ) { scanf ( p[i].s ) ; scanf ( p[i].l ) ; scanf ( p[i].a ) ; //scanf ( "%d%d%d" , &p[i].s , &p[i].l , &p[i].a ) ; b[i] = p[i].a ; } p[n + 1] = People ( 0 , -1 , -1 ) ; p[n + 2] = People ( 0 , 1000000001 , 1000000001 ) ; b[n + 1] = -1 ; b[n + 2] = 1000000001 ; n += 2 ; sort ( p + 1 , p + n + 1 ) ; For ( i , 1 , n ) a[i] = p[i].l ; cnt = unique ( n ) ; build ( root[0] , 1 , cnt ) ; For ( i , 1 , n ) insert ( root[i - 1] , root[i] , hash ( p[i].a ) , p[i].s , 1 , cnt ) ; scanf ( "%d" , &m ) ; while ( m -- ) { scanf ( ll ) ; scanf ( hl ) ; scanf ( la ) ; scanf ( ha ) ; //canf ( "%I64d%I64d%I64d%I64d" , &ll , &hl , &la , &ha ) ; ll += ans ; hl -= ans ; la += ans ; ha -= ans ; if ( ll > hl ) swap ( ll , hl ) ; if ( la > ha ) swap ( la , ha ) ; ll = max ( -1LL , ll ) ; la = max ( -1LL , la ) ; hl = min ( 1000000001LL , hl ) ; ha = min ( 1000000001LL , ha ) ; ll = lower_bound ( ll , a , 1 , n ) ; hl = upper_bound ( hl , a , 1 , n ) ; la = lower_bound ( la , b , 1 , cnt ) ; ha = upper_bound ( ha , b , 1 , cnt ) ; //printf ( "%I64d %I64d %I64d %I64d\n" , ll , hl , la , ha ) ; ans = query ( root[ll - 1] , root[hl] , ha , 1 , cnt ) - query ( root[ll - 1] , root[hl] , la - 1 , 1 , cnt ) ; printf ( "%I64d\n" , ans ) ; } } int main () { while ( ~scanf ( "%d" , &n ) ) solve () ; return 0 ; }