题目
点这里看题目。
分析
设(F(T))为温度为(T)的时候火系战士能量和,(I(T))为(T)时冰系战士能量和。
显然我们需要求:
[max{min{F(T),I(T)}}
]
另一个显然的事情是,(F(T))是一个后缀和,(I(T))是一个前缀和;因而(F(T))单减,(I(T))单增。
那么(min{F(T),I(T)})就应该是一个有最高平台的函数。
更进一步的,设(T_1=max{T|I(T)le F(T)},T_2=min{T|F(T)<I(T)}),那么我们可以知道,峰值要么是(I(T_1)),要么是(F(T_2))。
首先我们可以离散化后,用树状数组维护一下(I)的前缀和和(F)的前缀差和。计算(F)的时候,我们用能量和减掉范围外的。
寻找(T_1),我们可以直接在树状数组上面二分。具体来说,我们实际上枚举步长来进行倍增,并利用树状数组得到当前的前缀信息。
寻找(F(T_2)),我们可以直接找出(T_1)的后继(T_2'),那么(F(T_2)=F(T_2'))。不过,有可能(T_2'<T_2),我们需要在树状数组上面把(F(T_2'))的值代入,二分找出(T_2)。
所以总共应该有两个二分,一个寻找(T_1),一个寻找(T_2)。
时间复杂度是(O(nlog_2n)),非常非常卡,需要卡常或者 O2 。
代码
#include <cmath>
#include <cstdio>
#include <algorithm>
const int MAXN = 2e6 + 5;
template<typename _T>
void read( _T &x )
{
x = 0;char s = getchar();int f = 1;
while( s > '9' || s < '0' ){if( s == '-' ) f = -1; s = getchar();}
while( s >= '0' && s <= '9' ){x = ( x << 3 ) + ( x << 1 ) + ( s - '0' ), s = getchar();}
x *= f;
}
template<typename _T>
void write( _T x )
{
if( x < 0 ){ putchar( '-' ); x = ( ~ x ) + 1; }
if( 9 < x ){ write( x / 10 ); }
putchar( x % 10 + '0' );
}
struct oper
{
int type, id, x, y;
}op[MAXN];
int F[MAXN], I[MAXN];
int temp[MAXN];
int typ[MAXN], T[MAXN], E[MAXN];
int Q, N, lg2, all;
void up( int &x ) { x += x & ( -x ); }
void down( int &x ) { x &= ( x - 1 ); }
void uptF( int x, const int v ) { for( ; x <= N ; up( x ) ) F[x] += v; }
void uptI( int x, const int v ) { for( ; x <= N ; up( x ) ) I[x] += v; }
int getF( int x ) { int ret = 0; for( ; x ; down( x ) ) ret += F[x]; return ret; }
int getI( int x ) { int ret = 0; for( ; x ; down( x ) ) ret += I[x]; return ret; }
int find1()
{
int p = 0, ice = 0, fire = 0, tmp;
for( int s = 1 << lg2 ; s ; s >>= 1 )
{
tmp = p + s;
if( tmp > N ) continue;
ice += I[tmp];
fire += F[tmp];
if( ice <= all - fire ) p = tmp;
else ice -= I[tmp], fire -= F[tmp];
}
return p;
}
int find2( const int tar )
{
int p = 0, fire = 0, tmp;
for( int s = 1 << lg2 ; s ; s >>= 1 )
{
tmp = p + s;
if( tmp > N ) continue;
fire += F[tmp];
if( all - fire >= tar ) p = tmp;
else fire -= F[tmp];
}
return p;
}
int main()
{
read( Q );
for( int i = 1 ; i <= Q ; i ++ )
{
read( op[i].type ), read( op[i].id );
if( op[i].type == 1 )
read( op[i].x ), read( op[i].y ), temp[++ N] = op[i].x;
}
std :: sort( temp + 1, temp + 1 + N );
N = std :: unique( temp + 1, temp + 1 + N ) - temp - 1;
lg2 = log2( N ); int pos, p1, e1, p2, e2;
for( int i = 1 ; i <= Q ; i ++ )
{
if( op[i].type == 1 )
{
pos = std :: lower_bound( temp + 1, temp + 1 + N, op[i].x ) - temp;
if( op[i].id ) all += op[i].y, uptF( pos + 1, op[i].y );
else uptI( pos, op[i].y );
typ[i] = op[i].id, T[i] = pos, E[i] = op[i].y;
}
else
{
pos = op[i].id;
if( typ[pos] ) all -= op[pos].y, uptF( T[pos] + 1, -E[pos] );
else uptI( T[pos], - E[pos] );
}
p1 = find1(), e1 = getI( p1 );
p2 = p1 == N ? N : p1 + 1, e2 = all - getF( p2 );
if( e1 == 0 && e2 == 0 ) { puts( "Peace" ); continue; }
if( e1 > e2 ) write( temp[p1] ), putchar( ' ' ), write( e1 * 2ll ), putchar( '
' );
else write( temp[find2( e2 )] ), putchar( ' ' ), write( e2 * 2ll ), putchar( '
' );
}
return 0;
}