题目链接:
题目大意:
给出一个反对角线之上的三角形,每次吃一条,可以选择向左吃,或向上吃,只能从反对角线上的点开始,问每次吃的时候能吃多少小块
题目分析:
首先考虑每次吃的时候,如果是向上吃,那么能够影响它的就是它右侧的点,找到目前它右侧的点中最近的左吃的,然后这个点会影响到当前点吃的高度,如果向左吃,那么找到左侧最近的向上吃的点,会影响向左吃的距离,那么获得最近的这种就是利用set中的low_bound和high_bound,然后利用并查集的思想,在每一点被更新之后,获取到更新到它的点的信息,因为向上吃的会被向左吃的更新,下一个向上吃的找最近的点时,会找到这个向上吃,所以让这个向上吃的点传递这个信息,否则复杂度增长o(n),目前这样做的复杂度是n*log(n),因为使用了set,所以常数比较大
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <set>
#define MAX 200007
#define PII pair<int,int>
#define v first
#define id second
using namespace std;
set<PII> con;
set<PII>::iterator it;
int n,m;
char s[50];
int x[MAX],y[MAX];
int main ( )
{
while ( ~scanf ( "%d%d" , &n , &m ) )
{
con.clear();
x[0] = y[0] = 0;
x[m+1] = y[m+1] = 0;
con.insert ( make_pair ( 0 , m+1 ) );
con.insert ( make_pair ( n+1 , m+1 ) );
for ( int i = 1 ; i <= m ; i++ )
{
scanf ( "%d%d" , &x[i] , &y[i] );
scanf ( "%s" , s );
if ( s[0] == 'U' )
it = con.lower_bound ( make_pair( x[i] , -1 ));
else
{
it = con.upper_bound ( make_pair( x[i] , m+1));
it--;
}
if ( it->v == x[i] )
{
puts ( "0" );
continue;
}
//cout << it->id << endl;
con.insert ( make_pair ( x[i] , i ) );
if ( s[0] == 'U' )
{
printf ( "%d\n" , y[i] - y[it->id] );
y[i] = y[it->id];
}
else
{
printf ( "%d\n" , x[i] - x[it->id] );
x[i] = x[it->id];
}
}
}
}