传送门:【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 ;
}