题目大意
给定一个无限长的的实数轴。给定
n
个互不相同数轴上整数点,表示每个动点的起始位置。每个动点有一个运动方向(向左或向右),以每秒1单位的速度运动。两个动点相遇后,会同时改变运动方向。现有
Data Constraint
n,q≤2∗105,t≤109
题解
首先注意两个结论:
- 两个点相遇后改变方向可以视为交换点的编号,而点的方向不变按原方向继续运动。
- 每个点在数轴上的相对位置是一定不变的。
然后,考虑将运动方向不同的点分成两组。
对于询问编号为
k
的点的位置,我们只需要找到在当前这个时间下与
这个可以二分套二分解决。
时间复杂度: O(nlog2)
SRC
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std ;
#define N 200000 + 10
typedef long long ll ;
struct Note {
int v , h ;
Note ( int V = 0 , int H = 0 ) { v = V , h = H ; }
} tp[N] ;
int p[N] , d[N] , Rank[N] ;
ll a[N] , b[N] ;
int n , Q , k , t ;
ll ans ;
bool cmp( Note a , Note b ) { return a.v < b.v ; }
bool Check( ll st ) {
int wz = 0 ;
int l = 1 , r = a[0] ;
while ( l <= r ) {
int mid = (l + r) / 2 ;
if ( (ll)a[mid] - t <= st ) l = mid + 1 , wz = mid ;
else r = mid - 1 ;
}
if ( wz >= k ) return 1 ;
if ( b[k-wz] + t <= st && b[0] >= k - wz ) return 1 ;
return 0 ;
}
int main() {
freopen( "bridge.in" , "r" , stdin ) ;
freopen( "bridge.out" , "w" , stdout ) ;
scanf( "%d" , &n ) ;
for (int i = 1 ; i <= n ; i ++ ) scanf( "%d" , &p[i] ) , tp[i] = Note( p[i] , i ) ;
for (int i = 1 ; i <= n ; i ++ ) {
scanf( "%d" , &d[i] ) ;
if ( d[i] ) b[++b[0]] = p[i] ;
else a[++a[0]] = p[i] ;
}
sort( tp + 1 , tp + n + 1 , cmp ) ;
for (int i = 1 ; i <= n ; i ++ ) Rank[tp[i].h] = i ;
sort( a + 1 , a + a[0] + 1 ) ;
sort( b + 1 , b + b[0] + 1 ) ;
scanf( "%d" , &Q ) ;
for (int i = 1 ; i <= Q ; i ++ ) {
scanf( "%d%d" , &k , &t ) ;
k = Rank[k+1] ;
ll l = -1e9-5000 , r = 2e9+5000 ;
while ( l <= r ) {
ll mid = (l + r) / 2 ;
if ( Check(mid) ) r = mid - 1 , ans = mid ;
else l = mid + 1 ;
}
printf( "%lld\n" , ans ) ;
}
return 0 ;
}
以上.