<commit_before>#include <vector>
#include <list>
#include <sstream>
#include <algorithm>
#include <boost/thread/pthread/mutex.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <boost/regex.hpp>
#include <boost/format.hpp>
#include "protocol_module_cinsert.h"

namespace l7vs
{

bool	is_tcp()
{
	return	true;
}

bool	is_udp()
{
	return	false;
}

void	replication_interrupt()
{
}

void	initialize(
				rs_list_itr_func_type	inlist_begin,
				rs_list_itr_func_type	inlist_end,
				rs_list_itr_next_func_type	inlist_next,
				boost::function< void( void ) >	inlist_lock,
				boost::function< void( void ) >	inlist_unlock )
{
}

void	finalize()
{
}

bool	is_use_sorry()
{
	return	true;
}

check_message_result	check_parameter( const std::vector< std::string >& args )
{
	check_message_result	check_result;
	return	check_result;
}

check_message_result	set_parameter( const std::vector< std::string >& args )
{
	check_message_result check_result;
	return check_result;
}

check_message_result	add_parameter( const std::vector< std::string >& args )
{
	check_message_result check_result;
	return check_result;
}

void	handle_rslist_update()
{
}

void	register_schedule( tcp_schedule_func_type inschedule )
{
}

void	register_schedule( udp_schedule_func_type inschedule )
{
}

EVENT_TAG	handle_session_initialize(
				const boost::thread::id up_thread_id,
				const boost::thread::id down_thread_id,
				const boost::asio::ip::tcp::endpoint& client_endpoint_tcp,
				const boost::asio::ip::udp::endpoint& client_endpoint_udp )
{
	return	STOP;
}
EVENT_TAG	handle_session_finalize(
				const boost::thread::id up_thread_id,
				const boost::thread::id down_thread_id )
{
	return	STOP;
}

EVENT_TAG	handle_accept( const boost::thread::id thread_id )
{
	return	STOP;
}

EVENT_TAG	handle_client_recv(
				const boost::thread::id thread_id,
				const boost::array< char, MAX_BUFFER_SIZE >& recvbuffer,
				const size_t recvlen )
{
	return	STOP;
}

EVENT_TAG	handle_realserver_select(
				const boost::thread::id thread_id,
				boost::asio::ip::tcp::endpoint & rs_endpoint )
{
	return	STOP;
}

EVENT_TAG	handle_realserver_select(
				const boost::thread::id thread_id,
				boost::asio::ip::udp::endpoint& rs_endpoint,
				boost::array< char, MAX_BUFFER_SIZE >& sendbuffer,
				size_t& datalen )
{
	return	STOP;
}

EVENT_TAG	handle_realserver_connect(
				const boost::thread::id thread_id,
				boost::array< char, MAX_BUFFER_SIZE >& sendbuffer,
				size_t& datalen )
{
	return	STOP;
}

EVENT_TAG	handle_realserver_connection_fail(
				const boost::thread::id thread_id,
				const boost::asio::ip::tcp::endpoint & rs_endpoint )
{
	return	STOP;
}

EVENT_TAG	handle_realserver_send( const boost::thread::id thread_id )
{
	return	STOP;
}

EVENT_TAG	handle_sorryserver_select(
				const boost::thread::id thread_id,
				boost::asio::ip::tcp::endpoint & sorry_endpoint )
{
	return	STOP;
}

EVENT_TAG	handle_sorryserver_connect(
				const boost::thread::id thread_id,
				boost::array< char, MAX_BUFFER_SIZE >& sendbuffer,
				size_t& datalen )
{
	return	STOP;
}

EVENT_TAG	handle_sorryserver_connection_fail(
				const boost::thread::id thread_id,
				const boost::asio::ip::tcp::endpoint & sorry_endpoint )
{
	return	STOP;
}

EVENT_TAG	handle_sorryserver_send( const boost::thread::id thread_id )
{
	return	STOP;
}

EVENT_TAG	handle_realserver_recv(
				const boost::thread::id thread_id,
				const boost::asio::ip::tcp::endpoint& rs_endpoint,
				const boost::array< char, MAX_BUFFER_SIZE >& recvbuffer,
				const size_t recvlen )
{
	return	STOP;
}

EVENT_TAG	handle_realserver_recv(
				const boost::thread::id thread_id,
				const boost::asio::ip::udp::endpoint& rs_endpoint,
				const boost::array< char, MAX_BUFFER_SIZE >& recvbuffer,
				const size_t recvlen )
{
	return	STOP;
}

EVENT_TAG	handle_sorryserver_recv(
				const boost::thread::id thread_id,
				const boost::asio::ip::tcp::endpoint& sorry_endpoint,
				const boost::array< char, MAX_BUFFER_SIZE >& recvbuffer,
				const size_t recvlen )
{
	return	STOP;
}

EVENT_TAG	handle_response_send_inform( const boost::thread::id thread_id )
{
	return	STOP;
}

EVENT_TAG	handle_client_connection_check(
				const boost::thread::id thread_id,
				boost::array< char, MAX_BUFFER_SIZE >& sendbuffer,
				size_t& datalen )
{
	return	STOP;
}

EVENT_TAG	handle_client_select(
				const boost::thread::id thread_id,
				boost::asio::ip::udp::endpoint& cl_endpoint,
				boost::array< char, MAX_BUFFER_SIZE >& sendbuffer,
				size_t& datalen )
{
	return	STOP;
}

EVENT_TAG	handle_client_send( const boost::thread::id thread_id )
{
	return	STOP;
}

EVENT_TAG	handle_client_disconnect( const boost::thread::id thread_id )
{
	return	STOP;
}

EVENT_TAG	handle_sorry_enable( const boost::thread::id thread_id )
{
	return	STOP;
}

EVENT_TAG	handle_sorry_disable( const boost::thread::id thread_id )
{
	return	STOP;
}

EVENT_TAG	handle_realserver_disconnect(
				const boost::thread::id thread_id,
				const boost::asio::ip::tcp::endpoint & rs_endpoint )
{
	return	STOP;
}

EVENT_TAG	handle_sorryserver_disconnect(
				const boost::thread::id thread_id,
				const boost::asio::ip::tcp::endpoint & sorry_endpoint )
{
	return	STOP;
}

EVENT_TAG	handle_realserver_close(
				const boost::thread::id thread_id,
				const boost::asio::ip::udp::endpoint & rs_endpoint )
{

	return	STOP;
}

}
<commit_msg><commit_after>#include <vector>
#include <list>
#include <sstream>
#include <algorithm>
#include <boost/thread/pthread/mutex.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <boost/regex.hpp>
#include <boost/format.hpp>
#include "protocol_module_cinsert.h"

namespace l7vs
{

protocol_module_cinsert::protocol_module_cinsert() : http_protocol_module_base( "cinsert" )
{
}

protocol_module_cinsert::~protocol_module_cinsert()
{
}

bool	protocol_module_cinsert::is_tcp()
{
	return	true;
}

bool	protocol_module_cinsert::is_udp()
{
	return	false;
}

void	protocol_module_cinsert::replication_interrupt()
{
	// NOP
	return;
}

void	protocol_module_cinsert::initialize(
				rs_list_itr_func_type			inlist_begin,
				rs_list_itr_func_type			inlist_end,
				rs_list_itr_next_func_type		inlist_next,
				boost::function< void( void ) >	inlist_lock,
				boost::function< void( void ) >	inlist_unlock )
{
	rs_list_begin	= inlist_begin;
	rs_list_end		= inlist_end;
	rs_list_next	= inlist_next;
	rs_list_lock	= inlist_lock;
	rs_list_unlock	= inlist_unlock;
}

void	protocol_module_cinsert::finalize()
{
	getloglevel.clear();
	putLogFatal.clear();
	putLogError.clear();
	putLogWarn.clear();
	putLogInfo.clear();
	putLogDebug.clear();

	rs_list_begin.clear();
	rs_list_end.clear();
	rs_list_next.clear();
	rs_list_lock.clear();
	rs_list_unlock.clear();

	replication_pay_memory.clear();
	replication_area_lock.clear();
	replication_area_unlock.clear();

	schedule_tcp.clear();
	schedule_udp.clear();

	cookie_expire	= 0;
	forwarded_for	= 0;
	reschedule		= 0;
	cookie_name.assign( '\0' );
	sorry_uri.assign( '\0' );
}

bool	protocol_module_cinsert::is_use_sorry()
{
	return	true;
}

protocol_module_cinsert::check_message_result
protocol_module_cinsert::check_parameter( const std::vector< std::string >& args )
{
	check_message_result	check_result;
	return	check_result;
}

protocol_module_cinsert::check_message_result
protocol_module_cinsert::set_parameter( const std::vector< std::string >& args )
{
	check_message_result check_result;
	return check_result;
}

protocol_module_cinsert::check_message_result
protocol_module_cinsert::add_parameter( const std::vector< std::string >& args )
{
	check_message_result check_result;
	return check_result;
}

void	protocol_module_cinsert::handle_rslist_update()
{
	// NOP
	return;
}

void	protocol_module_cinsert::register_schedule( tcp_schedule_func_type inschedule )
{
	schedule_tcp = inschedule;
}

void	protocol_module_cinsert::register_schedule( udp_schedule_func_type inschedule )
{
	// NOP
	return;
}

protocol_module_cinsert::EVENT_TAG
protocol_module_cinsert::handle_session_initialize(
				const boost::thread::id up_thread_id,
				const boost::thread::id down_thread_id,
				const boost::asio::ip::tcp::endpoint& client_endpoint_tcp,
				const boost::asio::ip::udp::endpoint& client_endpoint_udp )
{

	session_thread_data_cinsert*	up_thread_data		= NULL;
	session_thread_data_cinsert*	down_thread_data	= NULL;
	recive_data*					client_recv_data	= NULL;
	char*							buffer				= NULL;

	try
	{
		up_thread_data	= new session_thread_data_cinsert;

		up_thread_data->thread_id				= up_thread_id;
		up_thread_data->thread_division			= THREAD_DIVISION_UP_STREAM;
		up_thread_data->pair_thread_id			= down_thread_id;
		up_thread_data->end_flag				= END_FLAG_OFF;
		up_thread_data->accept_end_flag			= ACCEPT_END_FLAG_OFF;
		up_thread_data->sorry_flag				= SORRY_FLAG_OFF;
		up_thread_data->sorryserver_switch_flag	= SORRYSERVER_SWITCH_FLAG_OFF;
		up_thread_data->realserver_switch_flag	= REALSERVER_SWITCH_FLAG_OFF;
		up_thread_data->client_endpoint_tcp		= client_endpoint_tcp;

		client_recv_data = new recive_data;
		client_recv_data->recive_buffer_max_size	= MAX_BUFFER_SIZE;
		client_recv_data->recive_buffer_rest_size	= MAX_BUFFER_SIZE;

		buffer = (char*)malloc( MAX_BUFFER_SIZE );

		client_recv_data->recive_buffer		= buffer;
		client_recv_data->recive_buffer_1	= buffer;

		buffer = (char*)malloc( MAX_BUFFER_SIZE );

		client_recv_data->recive_buffer_2	= buffer;

		up_thread_data->recive_data_map[ client_endpoint_tcp ] = client_recv_data;

		down_thread_data	= new session_thread_data_cinsert;

		down_thread_data->thread_id					= down_thread_id;
		down_thread_data->thread_division			= THREAD_DIVISION_DOWN_STREAM;
		down_thread_data->pair_thread_id			= up_thread_id;
		down_thread_data->end_flag					= END_FLAG_OFF;
		down_thread_data->accept_end_flag			= ACCEPT_END_FLAG_OFF;
		down_thread_data->sorry_flag				= SORRY_FLAG_OFF;
		down_thread_data->sorryserver_switch_flag	= SORRYSERVER_SWITCH_FLAG_OFF;
		down_thread_data->realserver_switch_flag	= REALSERVER_SWITCH_FLAG_OFF;
		down_thread_data->client_endpoint_tcp		= client_endpoint_tcp;

		{
			boost::mutex::scoped_lock	lock( session_thread_data_map_mutex );
			session_thread_data_map[ up_thread_id ]		= up_thread_data;
			session_thread_data_map[ down_thread_id ]	= down_thread_data;
		}

	} catch (const std::exception& ex)
	{
		return FINALIZE;
	} catch (...)
	{
		return FINALIZE;
	}

	return	ACCEPT;

}

protocol_module_cinsert::EVENT_TAG
protocol_module_cinsert::handle_session_finalize(
				const boost::thread::id up_thread_id,
				const boost::thread::id down_thread_id )
{
	session_thread_data_cinsert*	thread_data = NULL;
	session_thread_data_map_itr			thread_data_itr;

	try
	{
		{
			boost::mutex::scoped_lock	lock( session_thread_data_map_mutex );
			thread_data_itr = session_thread_data_map.find( up_thread_id );
			if( thread_data_itr != session_thread_data_map.end() )
			{
				thread_data = thread_data_itr->second;
				session_thread_data_map.erase( up_thread_id );
			}
		}

		if( thread_data != NULL )
		{
		}

	} catch (const std::exception& ex)
	{
	} catch (...)
	{
	}
	return	STOP;
}

protocol_module_cinsert::EVENT_TAG
protocol_module_cinsert::handle_accept( const boost::thread::id thread_id )
{
	return	STOP;
}

protocol_module_cinsert::EVENT_TAG
protocol_module_cinsert::handle_client_recv(
				const boost::thread::id thread_id,
				const boost::array< char, MAX_BUFFER_SIZE >& recvbuffer,
				const size_t recvlen )
{
	return	STOP;
}

protocol_module_cinsert::EVENT_TAG
protocol_module_cinsert::handle_realserver_select(
				const boost::thread::id thread_id,
				boost::asio::ip::tcp::endpoint & rs_endpoint )
{
	return	STOP;
}

protocol_module_cinsert::EVENT_TAG
protocol_module_cinsert::handle_realserver_select(
				const boost::thread::id thread_id,
				boost::asio::ip::udp::endpoint& rs_endpoint,
				boost::array< char, MAX_BUFFER_SIZE >& sendbuffer,
				size_t& datalen )
{
	// NOP
	return	STOP;
}

protocol_module_cinsert::EVENT_TAG
protocol_module_cinsert::handle_realserver_connect(
				const boost::thread::id thread_id,
				boost::array< char, MAX_BUFFER_SIZE >& sendbuffer,
				size_t& datalen )
{
	return	STOP;
}

protocol_module_cinsert::EVENT_TAG
protocol_module_cinsert::handle_realserver_connection_fail(
				const boost::thread::id thread_id,
				const boost::asio::ip::tcp::endpoint & rs_endpoint )
{
	return	STOP;
}

protocol_module_cinsert::EVENT_TAG
protocol_module_cinsert::handle_realserver_send( const boost::thread::id thread_id )
{
	return	STOP;
}

protocol_module_cinsert::EVENT_TAG
protocol_module_cinsert::handle_sorryserver_select(
				const boost::thread::id thread_id,
				boost::asio::ip::tcp::endpoint & sorry_endpoint )
{
	return	STOP;
}

protocol_module_cinsert::EVENT_TAG
protocol_module_cinsert::handle_sorryserver_connect(
				const boost::thread::id thread_id,
				boost::array< char, MAX_BUFFER_SIZE >& sendbuffer,
				size_t& datalen )
{
	return	STOP;
}

protocol_module_cinsert::EVENT_TAG
protocol_module_cinsert::handle_sorryserver_connection_fail(
				const boost::thread::id thread_id,
				const boost::asio::ip::tcp::endpoint & sorry_endpoint )
{
	return	STOP;
}

protocol_module_cinsert::EVENT_TAG
protocol_module_cinsert::handle_sorryserver_send( const boost::thread::id thread_id )
{
	return	STOP;
}

protocol_module_cinsert::EVENT_TAG
protocol_module_cinsert::handle_realserver_recv(
				const boost::thread::id thread_id,
				const boost::asio::ip::tcp::endpoint& rs_endpoint,
				const boost::array< char, MAX_BUFFER_SIZE >& recvbuffer,
				const size_t recvlen )
{
	return	STOP;
}

protocol_module_cinsert::EVENT_TAG
protocol_module_cinsert::handle_realserver_recv(
				const boost::thread::id thread_id,
				const boost::asio::ip::udp::endpoint& rs_endpoint,
				const boost::array< char, MAX_BUFFER_SIZE >& recvbuffer,
				const size_t recvlen )
{
	return	STOP;
}

protocol_module_cinsert::EVENT_TAG
protocol_module_cinsert::handle_sorryserver_recv(
				const boost::thread::id thread_id,
				const boost::asio::ip::tcp::endpoint& sorry_endpoint,
				const boost::array< char, MAX_BUFFER_SIZE >& recvbuffer,
				const size_t recvlen )
{
	return	STOP;
}

protocol_module_cinsert::EVENT_TAG
protocol_module_cinsert::handle_response_send_inform( const boost::thread::id thread_id )
{
	// NOP
	return	STOP;
}

protocol_module_cinsert::EVENT_TAG
protocol_module_cinsert::handle_client_connection_check(
				const boost::thread::id thread_id,
				boost::array< char, MAX_BUFFER_SIZE >& sendbuffer,
				size_t& datalen )
{
	return	STOP;
}

protocol_module_cinsert::EVENT_TAG
protocol_module_cinsert::handle_client_select(
				const boost::thread::id thread_id,
				boost::asio::ip::udp::endpoint& cl_endpoint,
				boost::array< char, MAX_BUFFER_SIZE >& sendbuffer,
				size_t& datalen )
{
	// NOP
	return	STOP;
}

protocol_module_cinsert::EVENT_TAG
protocol_module_cinsert::handle_client_send( const boost::thread::id thread_id )
{
	return	STOP;
}

protocol_module_cinsert::EVENT_TAG
protocol_module_cinsert::handle_client_disconnect( const boost::thread::id thread_id )
{
	return	STOP;
}

protocol_module_cinsert::EVENT_TAG
protocol_module_cinsert::handle_sorry_enable( const boost::thread::id thread_id )
{
	return	STOP;
}

protocol_module_cinsert::EVENT_TAG
protocol_module_cinsert::handle_sorry_disable( const boost::thread::id thread_id )
{
	return	STOP;
}

protocol_module_cinsert::EVENT_TAG
protocol_module_cinsert::handle_realserver_disconnect(
				const boost::thread::id thread_id,
				const boost::asio::ip::tcp::endpoint & rs_endpoint )
{
	return	STOP;
}

protocol_module_cinsert::EVENT_TAG
protocol_module_cinsert::handle_sorryserver_disconnect(
				const boost::thread::id thread_id,
				const boost::asio::ip::tcp::endpoint & sorry_endpoint )
{
	return	STOP;
}

protocol_module_cinsert::EVENT_TAG
protocol_module_cinsert::handle_realserver_close(
				const boost::thread::id thread_id,
				const boost::asio::ip::udp::endpoint & rs_endpoint )
{
	// NOP
	return	STOP;
}

}
<|endoftext|>


<commit_before>#include <iostream>
#include <iomanip> // << fixed << setprecision(xxx)
#include <algorithm> // do { } while ( next_permutation(A, A+xxx) ) ;
#include <vector>
#include <string> // to_string(nnn) // substr(m, n) // stoi(nnn)
#include <complex>
#include <tuple> // get<n>(xxx)
#include <queue>
#include <stack>
#include <map> // if (M.find(key) != M.end()) { }
#include <set> // S.insert(M);
// if (S.find(key) != S.end()) { }
// for (auto it=S.begin(); it != S.end(); it++) { }
// auto it = S.lower_bound(M);
#include <random> // random_device rd; mt19937 mt(rd());
#include <cctype>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib> // atoi(xxx)
using namespace std;

#define DEBUG 0 // change 0 -> 1 if we need debug.
// insert #if<tab> by my emacs. #if DEBUG == 1 ... #end

typedef long long ll;

// const int dx[4] = {1, 0, -1, 0};
// const int dy[4] = {0, 1, 0, -1};

// const int C = 1e6+10;
// const ll M = 1000000007;

typedef tuple<int, ll> path;

int N;
vector<path> V[100010];
int Q, K;
path parent[100010];
ll memo[100010];
int x[100010];
int y[100010];

ll dist(int n) {
  if (memo[n] != -1) return memo[n];
  if (n == K) return memo[n] = 0;
  int p = get<0>(parent[n]);
  return memo[n] = dist(p) + get<1>(parent[n]);
}

int main () {
  cin >> N;
  for (auto i = 0; i < N-1; ++i) {
    int a, b, c;
    cin >> a >> b >> c;
    a--;
    b--;
    V[a].push_back(path(b, c));
    V[b].push_back(path(a, c));
  }
  cin >> Q >> K;
  K--;
  for (auto i = 0; i < Q; ++i) {
    cin >> x[i] >> y[i];
    x[i]--;
    y[i]--;
  }
  stack<int> S;
  S.push(K);
  parent[K] = path(-1, 0);
  while (!S.empty()) {
    int now = S.top();
    S.pop();
    for (auto x : V[now]) {
      int next = get<0>(x);
      ll d = get<1>(x);
      if (next != get<0>(parent[now])) {
        parent[next] = path(now, d);
        S.push(next);
      }
    }
  }
  for (auto i = 0; i < Q; ++i) {
    cout << dist(x[i]) + dist(y[i]) << endl;
  }
}
<commit_msg>submit D.cpp to 'D - Transit Tree Path' (abc070) [C++14 (GCC 5.4.1)]<commit_after>#include <iostream>
#include <iomanip> // << fixed << setprecision(xxx)
#include <algorithm> // do { } while ( next_permutation(A, A+xxx) ) ;
#include <vector>
#include <string> // to_string(nnn) // substr(m, n) // stoi(nnn)
#include <complex>
#include <tuple> // get<n>(xxx)
#include <queue>
#include <stack>
#include <map> // if (M.find(key) != M.end()) { }
#include <set> // S.insert(M);
// if (S.find(key) != S.end()) { }
// for (auto it=S.begin(); it != S.end(); it++) { }
// auto it = S.lower_bound(M);
#include <random> // random_device rd; mt19937 mt(rd());
#include <cctype>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib> // atoi(xxx)
using namespace std;

#define DEBUG 0 // change 0 -> 1 if we need debug.
// insert #if<tab> by my emacs. #if DEBUG == 1 ... #end

typedef long long ll;

// const int dx[4] = {1, 0, -1, 0};
// const int dy[4] = {0, 1, 0, -1};

// const int C = 1e6+10;
// const ll M = 1000000007;

typedef tuple<int, ll> path;

int N;
vector<path> V[100010];
int Q, K;
path parent[100010];
ll memo[100010];
int x[100010];
int y[100010];

ll dist(int n) {
  if (memo[n] != -1) return memo[n];
  if (n == K) return memo[n] = 0;
  int p = get<0>(parent[n]);
  return memo[n] = dist(p) + get<1>(parent[n]);
}

int main () {
  cin >> N;
  for (auto i = 0; i < N-1; ++i) {
    int a, b, c;
    cin >> a >> b >> c;
    a--;
    b--;
    V[a].push_back(path(b, c));
    V[b].push_back(path(a, c));
  }
  cin >> Q >> K;
  K--;
  for (auto i = 0; i < Q; ++i) {
    cin >> x[i] >> y[i];
    x[i]--;
    y[i]--;
  }
  fill(memo, memo+100010, -1);
  stack<int> S;
  S.push(K);
  parent[K] = path(-1, 0);
  while (!S.empty()) {
    int now = S.top();
    S.pop();
    for (auto x : V[now]) {
      int next = get<0>(x);
      ll d = get<1>(x);
      if (next != get<0>(parent[now])) {
        parent[next] = path(now, d);
        S.push(next);
      }
    }
  }
  for (auto i = 0; i < Q; ++i) {
    cout << dist(x[i]) + dist(y[i]) << endl;
  }
}
<|endoftext|>


<commit_before>/**
 * File    : B.cpp
 * Author  : Kazune Takahashi
 * Created : 11/20/2018, 11:10:45 PM
 * Powered by Visual Studio Code
 */

#include <iostream>
#include <iomanip>   // << fixed << setprecision(xxx)
#include <algorithm> // do { } while ( next_permutation(A, A+xxx) ) ;
#include <vector>
#include <string> // to_string(nnn) // substr(m, n) // stoi(nnn)
#include <complex>
#include <tuple>
#include <queue>
#include <stack>
#include <map> // if (M.find(key) != M.end()) { }
#include <set>
#include <functional>
#include <random> // auto rd = bind(uniform_int_distribution<int>(0, 9), mt19937(19920725));
#include <chrono> // std::chrono::system_clock::time_point start_time, end_time;
// start = std::chrono::system_clock::now();
// double elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(end_time-start_time).count();
#include <cctype>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib>
using namespace std;

#define DEBUG 0 // change 0 -> 1 if we need debug.

typedef long long ll;

// const int dx[4] = {1, 0, -1, 0};
// const int dy[4] = {0, 1, 0, -1};

// const int C = 1e6+10;
// const ll M = 1000000007;

int main()
{
  string A, B;
  cin >> A >> B;
  if (A == B)
  {
    cout << "EQUAL" << endl;
    return 0;
  }
  if (A.size() > B.size())
  {
    cout << "GREATER" << endl;
  }
  else if (A.size() < B.size())
  {
    cout << "LESS" << endl;
  }
  else
  {
    for (auto i = 0; i < (int)A.size(); i++)
    {
      if (A[i] > B[i])
      {
        cout << "GREATER" << endl;
        return 0;
      }
      else if (A[i] < B[i])
      {
        cout << "LESS" << endl;
        return 0;
      }
    }
  }
  return 1;
}<commit_msg>submit B.cpp to 'B - Comparison' (abc059) [C++14 (GCC 5.4.1)]<commit_after>/**
 * File    : B.cpp
 * Author  : Kazune Takahashi
 * Created : 11/20/2018, 11:10:45 PM
 * Powered by Visual Studio Code
 */

#include <iostream>
#include <iomanip>   // << fixed << setprecision(xxx)
#include <algorithm> // do { } while ( next_permutation(A, A+xxx) ) ;
#include <vector>
#include <string> // to_string(nnn) // substr(m, n) // stoi(nnn)
#include <complex>
#include <tuple>
#include <queue>
#include <stack>
#include <map> // if (M.find(key) != M.end()) { }
#include <set>
#include <functional>
#include <random> // auto rd = bind(uniform_int_distribution<int>(0, 9), mt19937(19920725));
#include <chrono> // std::chrono::system_clock::time_point start_time, end_time;
// start = std::chrono::system_clock::now();
// double elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(end_time-start_time).count();
#include <cctype>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib>
using namespace std;

#define DEBUG 0 // change 0 -> 1 if we need debug.

typedef long long ll;

// const int dx[4] = {1, 0, -1, 0};
// const int dy[4] = {0, 1, 0, -1};

// const int C = 1e6+10;
// const ll M = 1000000007;

int main()
{
  string A, B;
  cin >> A >> B;
  if (A == B)
  {
    cout << "EQUAL" << endl;
    return 0;
  }
  if (A.size() > B.size())
  {
    cout << "GREATER" << endl;
    return 0;
  }
  else if (A.size() < B.size())
  {
    cout << "LESS" << endl;
    return 0;
  }
  else
  {
    for (auto i = 0; i < (int)A.size(); i++)
    {
      if (A[i] > B[i])
      {
        cout << "GREATER" << endl;
        return 0;
      }
      else if (A[i] < B[i])
      {
        cout << "LESS" << endl;
        return 0;
      }
    }
  }
  return 1;
}<|endoftext|>


<commit_before>#define DEBUG 1

/**
 * File    : D.cpp
 * Author  : Kazune Takahashi
 * Created : 4/13/2019, 9:08:24 PM
 * Powered by Visual Studio Code
 */

#include <iostream>
#include <iomanip>   // << fixed << setprecision(xxx)
#include <algorithm> // do { } while ( next_permutation(A, A+xxx) ) ;
#include <vector>
#include <string> // to_string(nnn) // substr(m, n) // stoi(nnn)
#include <complex>
#include <tuple>
#include <queue>
#include <stack>
#include <map> // if (M.find(key) != M.end()) { }
#include <set>
#include <functional>
#include <random> // auto rd = bind(uniform_int_distribution<int>(0, 9), mt19937(10101010));
#include <chrono> // std::chrono::system_clock::time_point start_time, end_time;
// start = std::chrono::system_clock::now();
// double elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(end_time-start_time).count();
#include <cctype>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib>
using namespace std;

typedef long long ll;

// const int dx[4] = {1, 0, -1, 0};
// const int dy[4] = {0, 1, 0, -1};

// const int C = 1e6+10;
// const ll M = 1000000007;

int N, K;
string S;
vector<int> V;

int main()
{
  cin >> N >> K >> S;
  bool one = true;
  int t = 0;
  for (auto i = 0; i < N; i++)
  {
    if (S[i] == '0' && one)
    {
      V.push_back(t);
      one = false;
      t = 1;
    }
    else if (S[i] == '1' && one)
    {
      t++;
    }
    else if (S[i] == '0' && !one)
    {
      t++;
    }
    else
    {
      V.push_back(t);
      one = true;
      t = 1;
    }
  }
  V.push_back(t);
  if (!one)
  {
    V.push_back(0);
  }
#if DEBUG == 1
  for (auto x : V)
  {
    cerr << x << " ";
  }
  cerr << endl;
#endif
  vector<int> imos(V.size() + 1, 0);
  for (auto i = 0; i < N; i++)
  {
    imos[i + 1] = imos[i] + V[i];
  }
#if DEBUG == 1
  for (auto x : imos)
  {
    cerr << x << " ";
  }
  cerr << endl;
#endif
  int seg = min(2 * K + 1, (int)V.size());
  int ans = 0;
  for (auto i = 0; i + seg <= (int)V.size(); i++)
  {
    ans = max(ans, imos[i + seg] - imos[i]);
  }
  cout << ans << endl;
}<commit_msg>submit D.cpp to 'D - Handstand' (abc124) [C++14 (GCC 5.4.1)]<commit_after>#define DEBUG 1

/**
 * File    : D.cpp
 * Author  : Kazune Takahashi
 * Created : 4/13/2019, 9:08:24 PM
 * Powered by Visual Studio Code
 */

#include <iostream>
#include <iomanip>   // << fixed << setprecision(xxx)
#include <algorithm> // do { } while ( next_permutation(A, A+xxx) ) ;
#include <vector>
#include <string> // to_string(nnn) // substr(m, n) // stoi(nnn)
#include <complex>
#include <tuple>
#include <queue>
#include <stack>
#include <map> // if (M.find(key) != M.end()) { }
#include <set>
#include <functional>
#include <random> // auto rd = bind(uniform_int_distribution<int>(0, 9), mt19937(10101010));
#include <chrono> // std::chrono::system_clock::time_point start_time, end_time;
// start = std::chrono::system_clock::now();
// double elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(end_time-start_time).count();
#include <cctype>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib>
using namespace std;

typedef long long ll;

// const int dx[4] = {1, 0, -1, 0};
// const int dy[4] = {0, 1, 0, -1};

// const int C = 1e6+10;
// const ll M = 1000000007;

int N, K;
string S;
vector<int> V;

int main()
{
  cin >> N >> K >> S;
  bool one = true;
  int t = 0;
  for (auto i = 0; i < N; i++)
  {
    if (S[i] == '0' && one)
    {
      V.push_back(t);
      one = false;
      t = 1;
    }
    else if (S[i] == '1' && one)
    {
      t++;
    }
    else if (S[i] == '0' && !one)
    {
      t++;
    }
    else
    {
      V.push_back(t);
      one = true;
      t = 1;
    }
  }
  V.push_back(t);
  if (!one)
  {
    V.push_back(0);
  }
#if DEBUG == 1
  for (auto x : V)
  {
    cerr << x << " ";
  }
  cerr << endl;
#endif
  vector<int> imos(V.size() + 1, 0);
  for (auto i = 0; i < N; i++)
  {
    imos[i + 1] = imos[i] + V[i];
  }
#if DEBUG == 1
  for (auto x : imos)
  {
    cerr << x << " ";
  }
  cerr << endl;
#endif
  int seg = min(2 * K + 1, (int)V.size());
  int ans = 0;
  for (auto i = 0; i + seg <= (int)V.size(); i++)
  {
    if (i % 2 == 0)
    {
      ans = max(ans, imos[i + seg] - imos[i]);
    }
  }
  cout << ans << endl;
}<|endoftext|>


<commit_before>#define DEBUG 1
/**
 * File    : F.cpp
 * Author  : Kazune Takahashi
 * Created : 5/18/2020, 10:33:43 PM
 * Powered by Visual Studio Code
 */
#include <algorithm>
#include <bitset>
#include <cassert>
#include <cctype>
#include <chrono>
#include <cmath>
#include <complex>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <functional>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <tuple>
#include <unordered_map>
#include <unordered_set>
#include <vector>
// ----- boost -----
#include <boost/rational.hpp>
#include <boost/multiprecision/cpp_int.hpp>
// ----- using directives and manipulations -----
using namespace std;
using boost::rational;
using boost::multiprecision::cpp_int;
using ll = long long;
template <typename T>
using max_heap = priority_queue<T>;
template <typename T>
using min_heap = priority_queue<T, vector<T>, greater<T>>;
// ----- constexpr for Mint and Combination -----
constexpr ll MOD{1000000007LL};
// constexpr ll MOD{998244353LL}; // be careful
constexpr ll MAX_SIZE{3000010LL};
// constexpr ll MAX_SIZE{30000010LL}; // if 10^7 is needed
// ----- ch_max and ch_min -----
template <typename T>
void ch_max(T &left, T right)
{
  if (left < right)
  {
    left = right;
  }
}
template <typename T>
void ch_min(T &left, T right)
{
  if (left > right)
  {
    left = right;
  }
}
// ----- Mint -----
template <ll MOD = MOD>
class Mint
{
public:
  ll x;
  Mint() : x{0LL} {}
  Mint(ll x) : x{(x % MOD + MOD) % MOD} {}
  Mint operator-() const { return x ? MOD - x : 0; }
  Mint &operator+=(const Mint &a)
  {
    if ((x += a.x) >= MOD)
    {
      x -= MOD;
    }
    return *this;
  }
  Mint &operator-=(const Mint &a) { return *this += -a; }
  Mint &operator++() { return *this += 1; }
  Mint operator++(int)
  {
    Mint tmp{*this};
    ++*this;
    return tmp;
  }
  Mint &operator--() { return *this -= 1; }
  Mint operator--(int)
  {
    Mint tmp{*this};
    --*this;
    return tmp;
  }
  Mint &operator*=(const Mint &a)
  {
    (x *= a.x) %= MOD;
    return *this;
  }
  Mint &operator/=(const Mint &a)
  {
    Mint b{a};
    return *this *= b.power(MOD - 2);
  }
  Mint operator+(const Mint &a) const { return Mint(*this) += a; }
  Mint operator-(const Mint &a) const { return Mint(*this) -= a; }
  Mint operator*(const Mint &a) const { return Mint(*this) *= a; }
  Mint operator/(const Mint &a) const { return Mint(*this) /= a; }
  bool operator<(const Mint &a) const { return x < a.x; }
  bool operator<=(const Mint &a) const { return x <= a.x; }
  bool operator>(const Mint &a) const { return x > a.x; }
  bool operator>=(const Mint &a) const { return x >= a.x; }
  bool operator==(const Mint &a) const { return x == a.x; }
  bool operator!=(const Mint &a) const { return !(*this == a); }
  const Mint power(ll N)
  {
    if (N == 0)
    {
      return 1;
    }
    else if (N % 2 == 1)
    {
      return *this * power(N - 1);
    }
    else
    {
      Mint half = power(N / 2);
      return half * half;
    }
  }
};
template <ll MOD>
Mint<MOD> operator+(ll lhs, const Mint<MOD> &rhs)
{
  return rhs + lhs;
}
template <ll MOD>
Mint<MOD> operator-(ll lhs, const Mint<MOD> &rhs)
{
  return -rhs + lhs;
}
template <ll MOD>
Mint<MOD> operator*(ll lhs, const Mint<MOD> &rhs)
{
  return rhs * lhs;
}
template <ll MOD>
Mint<MOD> operator/(ll lhs, const Mint<MOD> &rhs)
{
  return Mint<MOD>{lhs} / rhs;
}
template <ll MOD>
istream &operator>>(istream &stream, Mint<MOD> &a)
{
  return stream >> a.x;
}
template <ll MOD>
ostream &operator<<(ostream &stream, const Mint<MOD> &a)
{
  return stream << a.x;
}
// ----- Combination -----
template <ll MOD = MOD, ll MAX_SIZE = MAX_SIZE>
class Combination
{
public:
  vector<Mint<MOD>> inv, fact, factinv;
  Combination() : inv(MAX_SIZE), fact(MAX_SIZE), factinv(MAX_SIZE)
  {
    inv[1] = 1;
    for (auto i = 2LL; i < MAX_SIZE; i++)
    {
      inv[i] = (-inv[MOD % i]) * (MOD / i);
    }
    fact[0] = factinv[0] = 1;
    for (auto i = 1LL; i < MAX_SIZE; i++)
    {
      fact[i] = Mint<MOD>(i) * fact[i - 1];
      factinv[i] = inv[i] * factinv[i - 1];
    }
  }
  Mint<MOD> operator()(int n, int k)
  {
    if (n >= 0 && k >= 0 && n - k >= 0)
    {
      return fact[n] * factinv[k] * factinv[n - k];
    }
    return 0;
  }
  Mint<MOD> catalan(int x, int y)
  {
    return (*this)(x + y, y) - (*this)(x + y, y - 1);
  }
};
// ----- for C++14 -----
using mint = Mint<MOD>;
using combination = Combination<MOD, MAX_SIZE>;
template <typename T>
T gcd(T x, T y) { return y ? gcd(y, x % y) : x; }
template <typename T>
T lcm(T x, T y) { return x / gcd(x, y) * y; }
// ----- for C++17 -----
template <typename T>
int popcount(T x) // C++20
{
  int ans{0};
  while (x != 0)
  {
    ans += x & 1;
    x >>= 1;
  }
  return ans;
}
// ----- frequently used constexpr -----
// constexpr double epsilon{1e-10};
// constexpr ll infty{1000000000000000LL}; // or
// constexpr int infty{1'000'000'010};
// constexpr int dx[4] = {1, 0, -1, 0};
// constexpr int dy[4] = {0, 1, 0, -1};
// ----- Yes() and No() -----
void Yes()
{
  cout << "Yes" << endl;
  exit(0);
}
void No()
{
  cout << "No" << endl;
  exit(0);
}
// ----- main() -----

int main()
{
  ll N, K;
  cin >> N >> K;
  ll X{static_cast<ll>(sqrt(N)) + 10};
  vector<vector<mint>> DP(K + 1, vector<mint>(X + 1, 0));
  vector<vector<mint>> DP2(K + 1, vector<mint>(X + 1, 0));
  vector<vector<mint>> SUM(K + 1, vector<mint>(X + 1, 0));
  vector<vector<mint>> SUM2(K + 1, vector<mint>(X + 1, 0));
  vector<mint> cnt(X + 1);
  for (auto j = 1; j <= X; ++j)
  {
    cnt[j] = max(N / j, X) - max(N / (j + 1), X);
  }
  DP[0][1] = 1;
  for (auto j = 1; j <= X; ++j)
  {
    SUM[0][j] = 1;
  }
  for (auto i = 1; i <= K; ++i)
  {
    for (auto j = 1; j <= X; ++j)
    {
      DP[i][j] = SUM[i - 1][min(X, N / j)] + SUM2[i - 1][X - 1] - SUM2[i - 1][j - 1];
      DP2[i][j] = cnt[j] * SUM[i - 1][j];
      SUM[i][j] = SUM[i][j - 1] + DP[i][j];
      SUM2[i][j] = SUM2[i][j - 1] + DP2[i][j];
    }
  }
  cout << SUM[K][X] + SUM2[K][X] << endl;
}
<commit_msg>submit F.cpp to 'F - Small Products' (abc132) [C++14 (GCC 5.4.1)]<commit_after>#define DEBUG 1
/**
 * File    : F.cpp
 * Author  : Kazune Takahashi
 * Created : 5/18/2020, 10:33:43 PM
 * Powered by Visual Studio Code
 */
#include <algorithm>
#include <bitset>
#include <cassert>
#include <cctype>
#include <chrono>
#include <cmath>
#include <complex>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <functional>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <tuple>
#include <unordered_map>
#include <unordered_set>
#include <vector>
// ----- boost -----
#include <boost/rational.hpp>
#include <boost/multiprecision/cpp_int.hpp>
// ----- using directives and manipulations -----
using namespace std;
using boost::rational;
using boost::multiprecision::cpp_int;
using ll = long long;
template <typename T>
using max_heap = priority_queue<T>;
template <typename T>
using min_heap = priority_queue<T, vector<T>, greater<T>>;
// ----- constexpr for Mint and Combination -----
constexpr ll MOD{1000000007LL};
// constexpr ll MOD{998244353LL}; // be careful
constexpr ll MAX_SIZE{3000010LL};
// constexpr ll MAX_SIZE{30000010LL}; // if 10^7 is needed
// ----- ch_max and ch_min -----
template <typename T>
void ch_max(T &left, T right)
{
  if (left < right)
  {
    left = right;
  }
}
template <typename T>
void ch_min(T &left, T right)
{
  if (left > right)
  {
    left = right;
  }
}
// ----- Mint -----
template <ll MOD = MOD>
class Mint
{
public:
  ll x;
  Mint() : x{0LL} {}
  Mint(ll x) : x{(x % MOD + MOD) % MOD} {}
  Mint operator-() const { return x ? MOD - x : 0; }
  Mint &operator+=(const Mint &a)
  {
    if ((x += a.x) >= MOD)
    {
      x -= MOD;
    }
    return *this;
  }
  Mint &operator-=(const Mint &a) { return *this += -a; }
  Mint &operator++() { return *this += 1; }
  Mint operator++(int)
  {
    Mint tmp{*this};
    ++*this;
    return tmp;
  }
  Mint &operator--() { return *this -= 1; }
  Mint operator--(int)
  {
    Mint tmp{*this};
    --*this;
    return tmp;
  }
  Mint &operator*=(const Mint &a)
  {
    (x *= a.x) %= MOD;
    return *this;
  }
  Mint &operator/=(const Mint &a)
  {
    Mint b{a};
    return *this *= b.power(MOD - 2);
  }
  Mint operator+(const Mint &a) const { return Mint(*this) += a; }
  Mint operator-(const Mint &a) const { return Mint(*this) -= a; }
  Mint operator*(const Mint &a) const { return Mint(*this) *= a; }
  Mint operator/(const Mint &a) const { return Mint(*this) /= a; }
  bool operator<(const Mint &a) const { return x < a.x; }
  bool operator<=(const Mint &a) const { return x <= a.x; }
  bool operator>(const Mint &a) const { return x > a.x; }
  bool operator>=(const Mint &a) const { return x >= a.x; }
  bool operator==(const Mint &a) const { return x == a.x; }
  bool operator!=(const Mint &a) const { return !(*this == a); }
  const Mint power(ll N)
  {
    if (N == 0)
    {
      return 1;
    }
    else if (N % 2 == 1)
    {
      return *this * power(N - 1);
    }
    else
    {
      Mint half = power(N / 2);
      return half * half;
    }
  }
};
template <ll MOD>
Mint<MOD> operator+(ll lhs, const Mint<MOD> &rhs)
{
  return rhs + lhs;
}
template <ll MOD>
Mint<MOD> operator-(ll lhs, const Mint<MOD> &rhs)
{
  return -rhs + lhs;
}
template <ll MOD>
Mint<MOD> operator*(ll lhs, const Mint<MOD> &rhs)
{
  return rhs * lhs;
}
template <ll MOD>
Mint<MOD> operator/(ll lhs, const Mint<MOD> &rhs)
{
  return Mint<MOD>{lhs} / rhs;
}
template <ll MOD>
istream &operator>>(istream &stream, Mint<MOD> &a)
{
  return stream >> a.x;
}
template <ll MOD>
ostream &operator<<(ostream &stream, const Mint<MOD> &a)
{
  return stream << a.x;
}
// ----- Combination -----
template <ll MOD = MOD, ll MAX_SIZE = MAX_SIZE>
class Combination
{
public:
  vector<Mint<MOD>> inv, fact, factinv;
  Combination() : inv(MAX_SIZE), fact(MAX_SIZE), factinv(MAX_SIZE)
  {
    inv[1] = 1;
    for (auto i = 2LL; i < MAX_SIZE; i++)
    {
      inv[i] = (-inv[MOD % i]) * (MOD / i);
    }
    fact[0] = factinv[0] = 1;
    for (auto i = 1LL; i < MAX_SIZE; i++)
    {
      fact[i] = Mint<MOD>(i) * fact[i - 1];
      factinv[i] = inv[i] * factinv[i - 1];
    }
  }
  Mint<MOD> operator()(int n, int k)
  {
    if (n >= 0 && k >= 0 && n - k >= 0)
    {
      return fact[n] * factinv[k] * factinv[n - k];
    }
    return 0;
  }
  Mint<MOD> catalan(int x, int y)
  {
    return (*this)(x + y, y) - (*this)(x + y, y - 1);
  }
};
// ----- for C++14 -----
using mint = Mint<MOD>;
using combination = Combination<MOD, MAX_SIZE>;
template <typename T>
T gcd(T x, T y) { return y ? gcd(y, x % y) : x; }
template <typename T>
T lcm(T x, T y) { return x / gcd(x, y) * y; }
// ----- for C++17 -----
template <typename T>
int popcount(T x) // C++20
{
  int ans{0};
  while (x != 0)
  {
    ans += x & 1;
    x >>= 1;
  }
  return ans;
}
// ----- frequently used constexpr -----
// constexpr double epsilon{1e-10};
// constexpr ll infty{1000000000000000LL}; // or
// constexpr int infty{1'000'000'010};
// constexpr int dx[4] = {1, 0, -1, 0};
// constexpr int dy[4] = {0, 1, 0, -1};
// ----- Yes() and No() -----
void Yes()
{
  cout << "Yes" << endl;
  exit(0);
}
void No()
{
  cout << "No" << endl;
  exit(0);
}
// ----- main() -----

int main()
{
  ll N, K;
  cin >> N >> K;
  ll X{static_cast<ll>(sqrt(N)) + 10};
  vector<vector<mint>> DP(K + 1, vector<mint>(X + 1, 0));
  vector<vector<mint>> DP2(K + 1, vector<mint>(X + 1, 0));
  vector<vector<mint>> SUM(K + 1, vector<mint>(X + 1, 0));
  vector<vector<mint>> SUM2(K + 1, vector<mint>(X + 1, 0));
  vector<mint> cnt(X + 1);
  for (auto j = 1; j <= X; ++j)
  {
    cnt[j] = max(N / j, X) - max(N / (j + 1), X);
  }
  DP[0][1] = 1;
  for (auto j = 1; j <= X; ++j)
  {
    SUM[0][j] = 1;
  }
  for (auto i = 1; i <= K; ++i)
  {
    for (auto j = 1; j <= X; ++j)
    {
      DP[i][j] = SUM[i - 1][min(X, N / j)] + SUM2[i - 1][X] - SUM2[i - 1][j - 1];
      DP2[i][j] = cnt[j] * SUM[i - 1][j];
      SUM[i][j] = SUM[i][j - 1] + DP[i][j];
      SUM2[i][j] = SUM2[i][j - 1] + DP2[i][j];
    }
  }
  cout << SUM[K][X] + SUM2[K][X] << endl;
}
<|endoftext|>


<commit_before>#define DEBUG 1
/**
 * File    : E.cpp
 * Author  : Kazune Takahashi
 * Created : 8/12/2019, 7:02:46 PM
 * Powered by Visual Studio Code
 */
#include <iostream>
#include <iomanip>
#include <algorithm>
#include <vector>
#include <string>
#include <complex>
#include <tuple>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <bitset>
#include <functional>
#include <random>
#include <chrono>
#include <cctype>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib>
using namespace std;
#define maxs(x, y) (x = max(x, y))
#define mins(x, y) (x = min(x, y))
using ll = long long;
class mint
{
public:
  static ll MOD;
  ll x;
  mint() : x(0) {}
  mint(ll x) : x(x % MOD) {}
  mint operator-() const { return x ? MOD - x : 0; }
  mint &operator+=(const mint &a)
  {
    if ((x += a.x) >= MOD)
    {
      x -= MOD;
    }
    return *this;
  }
  mint &operator-=(const mint &a) { return *this += -a; }
  mint &operator*=(const mint &a)
  {
    (x *= a.x) %= MOD;
    return *this;
  }
  mint &operator/=(const mint &a)
  {
    mint b{a};
    return *this *= b.power(MOD - 2);
  }
  mint operator+(const mint &a) const { return mint(*this) += a; }
  mint operator-(const mint &a) const { return mint(*this) -= a; }
  mint operator*(const mint &a) const { return mint(*this) *= a; }
  mint operator/(const mint &a) const { return mint(*this) /= a; }
  bool operator<(const mint &a) const { return x < a.x; }
  bool operator==(const mint &a) const { return x == a.x; }
  const mint power(ll N)
  {
    if (N == 0)
    {
      return 1;
    }
    else if (N % 2 == 1)
    {
      return *this * power(N - 1);
    }
    else
    {
      mint half = power(N / 2);
      return half * half;
    }
  }
};
ll mint::MOD = 1e9 + 7;
istream &operator>>(istream &stream, mint &a) { return stream >> a.x; }
ostream &operator<<(ostream &stream, const mint &a) { return stream << a.x; }
class combination
{
public:
  vector<mint> inv, fact, factinv;
  static int MAX_SIZE;
  combination() : inv(MAX_SIZE), fact(MAX_SIZE), factinv(MAX_SIZE)
  {
    inv[1] = 1;
    for (auto i = 2; i < MAX_SIZE; i++)
    {
      inv[i] = (-inv[mint::MOD % i]) * (mint::MOD / i);
    }
    fact[0] = factinv[0] = 1;
    for (auto i = 1; i < MAX_SIZE; i++)
    {
      fact[i] = mint(i) * fact[i - 1];
      factinv[i] = inv[i] * factinv[i - 1];
    }
  }
  mint operator()(int n, int k)
  {
    if (n >= 0 && k >= 0 && n - k >= 0)
    {
      return fact[n] * factinv[k] * factinv[n - k];
    }
    return 0;
  }
};
int combination::MAX_SIZE = 3000010;
ll gcd(ll x, ll y) { return y ? gcd(y, x % y) : x; }
// constexpr double epsilon = 1e-10;
// constexpr ll infty = 1000000000000000LL;
// constexpr int dx[4] = {1, 0, -1, 0};
// constexpr int dy[4] = {0, 1, 0, -1};
void Yes()
{
  cout << "Yes" << endl;
  exit(0);
}
void No()
{
  cout << "No" << endl;
  exit(0);
}

vector<int> count(string const &S)
{
  vector<int> cnt(3, 0);
  for (auto x : S)
  {
    cnt[x - 'A']++;
  }
  return cnt;
}

string reduce(string const &S)
{
  stringstream res{};
  char c{'x'};
  for (auto x : S)
  {
    if (x == c)
    {
      continue;
    }
    else
    {
      res << x;
      c = x;
    }
  }
  return res.str();
}

map<char, char> make_map(string const &S)
{
  vector<int> cnt = count(S);
  vector<tuple<int, char>> V;
  for (auto i = 0; i < 3; i++)
  {
    V.emplace_back(cnt[i], 'A' + i);
  }
  sort(V.begin(), V.end());
  map<char, char> res;
  for (auto i = 0; i < 3; i++)
  {
    res[get<1>(V[i])] = 'A' + i;
  }
  return res;
}

map<char, char> make_rev(map<char, char> const &M)
{
  map<char, char> res;
  for (auto x : M)
  {
    res[x.second] = x.first;
  }
  return res;
}

string convert(string const &S, map<char, char> const &M)
{
  stringstream SS{};
  for (auto x : S)
  {
    SS << M.at(x);
  }
  return SS.str();
}

vector<string> split(string const &S, char c)
{
  vector<string> res;
  stringstream SS{};
  for (auto x : S)
  {
    if (x == c)
    {
      res.push_back(SS.str());
      SS.str({});
    }
    else
    {
      SS << x;
    }
  }
  res.push_back(SS.str());
  return res;
}

string make_ans(string const &S)
{
  vector<int> cnt = count(S);
  assert(cnt[0] <= cnt[1] && cnt[1] == cnt[2]);
  vector<string> V = split(S, 'A');
#if DEBUG == 1
  for (auto i = 0u; i < V.size(); i++)
  {
    cerr << "V[" << i << "] = " << V[i] << endl;
  }
#endif
  vector<int> now(3, 0);
  vector<vector<bool>> used(V.size());
  for (auto i = 0u; i < V.size(); i++)
  {
    used[i] = vector<bool>(V[i].size(), false);
  }
  // 1st step
  for (auto i = 0u; i < V.size(); i++)
  {
    if (V[i].size() % 2 == 1)
    {
      used[i][0] = true;
      now[V[i][0] - 'A']++;
    }
  }
#if DEBUG == 1
  for (auto i = 0; i < 3; i++)
  {
    cerr << "now[" << i << "] = " << now[i] << endl;
  }
#endif
  assert(now[0] == 0 && now[1] == now[2]);
  // 2nd step
  for (auto i = 1u; i < V.size() - 1; i++)
  {
    if (V[i].size() % 2 == 0)
    {
      used[i][0] = used[i][1] = true;
      now[V[i][0] - 'A']++;
      now[V[i][1] - 'A']++;
    }
  }
  assert(now[0] == 0 && now[1] == now[2]);
  // 3rd step
  if (now[1] < cnt[0])
  {
    for (auto i = 0u; i < V.size(); i++)
    {
      int num = V[i].size() - 1;
      while (num >= 1 && !used[i][num] && !used[i][num - 1])
      {
        used[i][num] = used[i][num - 1] = true;
        now[V[i][num] - 'A']++;
        now[V[i][num - 1] - 'A']++;
        num -= 2;
        if (now[1] == cnt[0])
        {
          break;
        }
      }
      if (now[1] == cnt[0])
      {
        break;
      }
    }
  }
  assert(now[0] == 0 && now[1] == now[2] && cnt[0] == now[1]);
  // make ans
  stringstream SS{};
  for (auto i = 0u; i < V.size(); i++)
  {
    for (auto j = 0u; j < V[i].size(); j++)
    {
      if (used[i][j])
      {
        SS << V[i][j];
      }
    }
    if (i < V.size() - 1)
    {
      SS << 'A';
    }
  }
  return SS.str();
}

string erase_C(string const &S)
{
  vector<int> cnt = count(S);
  stringstream SS{};
  for (auto i = 0u; i < S.size(); i++)
  {
    if (cnt[2] > cnt[1])
    {
      if (S[i] == 'C')
      {
        if (i - 1 >= 0 && i + 1 < S.size())
        {
          if ((S[i - 1] == 'A' && S[i + 1] == 'B') || (S[i - 1] == 'B' && S[i + 1] == 'A'))
          {
            cnt[2]--;
            continue;
          }
        }
        else
        {
          cnt[2]--;
          continue;
        }
      }
    }
    SS << S[i];
#if DEBUG == 1
    cerr << "SS.str() = " << SS.str() << endl;
#endif
  }
  return SS.str();
}

string erase_AC(string const &S)
{
  vector<int> cnt = count(S);
  assert(cnt[0] <= cnt[1] && cnt[1] < cnt[2]);
  stringstream res{};
  for (auto i = 0u; i < S.size(); i++)
  {
    if (cnt[1] < cnt[2] && i < S.size() - 1 && S[i] == 'A' && S[i + 1] == 'C')
    {
      ++i;
      cnt[0]--;
      cnt[2]--;
    }
    else
    {
      res << S[i];
    }
  }
  return res.str();
}

int main()
{
  string S;
  cin >> S;
  S = reduce(S);
  map<char, char> M, R;
  M = make_map(S);
  R = make_rev(M);
  S = convert(S, M);
#if DEBUG == 1
  cerr << "S = " << S << endl;
#endif
  vector<int> cnt = count(S);
  if (cnt[1] < cnt[2])
  {
    S = erase_C(S);
#if DEBUG == 1
    cerr << "S = " << S << endl;
#endif
    cnt = count(S);
    if (cnt[1] < cnt[2])
    {
      S = erase_AC(S);
#if DEBUG == 1
      cerr << "S = " << S << endl;
#endif
    }
  }
  string ans{make_ans(S)};
#if DEBUG == 1
  cerr << "ans = " << ans << endl;
#endif
  ans = convert(ans, R);
  cout << ans << endl;
}<commit_msg>tried E.cpp to 'E'<commit_after>#define DEBUG 1
/**
 * File    : E.cpp
 * Author  : Kazune Takahashi
 * Created : 8/12/2019, 7:02:46 PM
 * Powered by Visual Studio Code
 */
#include <iostream>
#include <iomanip>
#include <algorithm>
#include <vector>
#include <string>
#include <complex>
#include <tuple>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <bitset>
#include <functional>
#include <random>
#include <chrono>
#include <cctype>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib>
using namespace std;
#define maxs(x, y) (x = max(x, y))
#define mins(x, y) (x = min(x, y))
using ll = long long;
class mint
{
public:
  static ll MOD;
  ll x;
  mint() : x(0) {}
  mint(ll x) : x(x % MOD) {}
  mint operator-() const { return x ? MOD - x : 0; }
  mint &operator+=(const mint &a)
  {
    if ((x += a.x) >= MOD)
    {
      x -= MOD;
    }
    return *this;
  }
  mint &operator-=(const mint &a) { return *this += -a; }
  mint &operator*=(const mint &a)
  {
    (x *= a.x) %= MOD;
    return *this;
  }
  mint &operator/=(const mint &a)
  {
    mint b{a};
    return *this *= b.power(MOD - 2);
  }
  mint operator+(const mint &a) const { return mint(*this) += a; }
  mint operator-(const mint &a) const { return mint(*this) -= a; }
  mint operator*(const mint &a) const { return mint(*this) *= a; }
  mint operator/(const mint &a) const { return mint(*this) /= a; }
  bool operator<(const mint &a) const { return x < a.x; }
  bool operator==(const mint &a) const { return x == a.x; }
  const mint power(ll N)
  {
    if (N == 0)
    {
      return 1;
    }
    else if (N % 2 == 1)
    {
      return *this * power(N - 1);
    }
    else
    {
      mint half = power(N / 2);
      return half * half;
    }
  }
};
ll mint::MOD = 1e9 + 7;
istream &operator>>(istream &stream, mint &a) { return stream >> a.x; }
ostream &operator<<(ostream &stream, const mint &a) { return stream << a.x; }
class combination
{
public:
  vector<mint> inv, fact, factinv;
  static int MAX_SIZE;
  combination() : inv(MAX_SIZE), fact(MAX_SIZE), factinv(MAX_SIZE)
  {
    inv[1] = 1;
    for (auto i = 2; i < MAX_SIZE; i++)
    {
      inv[i] = (-inv[mint::MOD % i]) * (mint::MOD / i);
    }
    fact[0] = factinv[0] = 1;
    for (auto i = 1; i < MAX_SIZE; i++)
    {
      fact[i] = mint(i) * fact[i - 1];
      factinv[i] = inv[i] * factinv[i - 1];
    }
  }
  mint operator()(int n, int k)
  {
    if (n >= 0 && k >= 0 && n - k >= 0)
    {
      return fact[n] * factinv[k] * factinv[n - k];
    }
    return 0;
  }
};
int combination::MAX_SIZE = 3000010;
ll gcd(ll x, ll y) { return y ? gcd(y, x % y) : x; }
// constexpr double epsilon = 1e-10;
// constexpr ll infty = 1000000000000000LL;
// constexpr int dx[4] = {1, 0, -1, 0};
// constexpr int dy[4] = {0, 1, 0, -1};
void Yes()
{
  cout << "Yes" << endl;
  exit(0);
}
void No()
{
  cout << "No" << endl;
  exit(0);
}

vector<int> count(string const &S)
{
  vector<int> cnt(3, 0);
  for (auto x : S)
  {
    cnt[x - 'A']++;
  }
  return cnt;
}

string reduce(string const &S)
{
  stringstream res{};
  char c{'x'};
  for (auto x : S)
  {
    if (x == c)
    {
      continue;
    }
    else
    {
      res << x;
      c = x;
    }
  }
  return res.str();
}

map<char, char> make_map(string const &S)
{
  vector<int> cnt = count(S);
  vector<tuple<int, char>> V;
  for (auto i = 0; i < 3; i++)
  {
    V.emplace_back(cnt[i], 'A' + i);
  }
  sort(V.begin(), V.end());
  map<char, char> res;
  for (auto i = 0; i < 3; i++)
  {
    res[get<1>(V[i])] = 'A' + i;
  }
  return res;
}

map<char, char> make_rev(map<char, char> const &M)
{
  map<char, char> res;
  for (auto x : M)
  {
    res[x.second] = x.first;
  }
  return res;
}

string convert(string const &S, map<char, char> const &M)
{
  stringstream SS{};
  for (auto x : S)
  {
    SS << M.at(x);
  }
  return SS.str();
}

vector<string> split(string const &S, char c)
{
  vector<string> res;
  stringstream SS{};
  for (auto x : S)
  {
    if (x == c)
    {
      res.push_back(SS.str());
      SS.str({});
    }
    else
    {
      SS << x;
    }
  }
  res.push_back(SS.str());
  return res;
}

string make_ans(string const &S)
{
  vector<int> cnt = count(S);
  assert(cnt[0] <= cnt[1] && cnt[1] == cnt[2]);
  vector<string> V = split(S, 'A');
#if DEBUG == 1
  for (auto i = 0u; i < V.size(); i++)
  {
    cerr << "V[" << i << "] = " << V[i] << endl;
  }
#endif
  vector<int> now(3, 0);
  vector<vector<bool>> used(V.size());
  for (auto i = 0u; i < V.size(); i++)
  {
    used[i] = vector<bool>(V[i].size(), false);
  }
  // 1st step
  for (auto i = 0u; i < V.size(); i++)
  {
    if (V[i].size() % 2 == 1)
    {
      used[i][0] = true;
      now[V[i][0] - 'A']++;
    }
  }
#if DEBUG == 1
  for (auto i = 0; i < 3; i++)
  {
    cerr << "now[" << i << "] = " << now[i] << endl;
  }
#endif
  assert(now[0] == 0 && now[1] == now[2]);
  // 2nd step
  for (auto i = 1u; i < V.size() - 1; i++)
  {
    if (V[i].size() % 2 == 0)
    {
      used[i][0] = used[i][1] = true;
      now[V[i][0] - 'A']++;
      now[V[i][1] - 'A']++;
    }
  }
  assert(now[0] == 0 && now[1] == now[2]);
  // 3rd step
  if (now[1] < cnt[0])
  {
    for (auto i = 0u; i < V.size(); i++)
    {
      int num = V[i].size() - 1;
      while (num >= 1 && !used[i][num] && !used[i][num - 1])
      {
        used[i][num] = used[i][num - 1] = true;
        now[V[i][num] - 'A']++;
        now[V[i][num - 1] - 'A']++;
        num -= 2;
        if (now[1] == cnt[0])
        {
          break;
        }
      }
      if (now[1] == cnt[0])
      {
        break;
      }
    }
  }
  assert(now[0] == 0 && now[1] == now[2] && cnt[0] == now[1]);
  // make ans
  stringstream SS{};
  for (auto i = 0u; i < V.size(); i++)
  {
    for (auto j = 0u; j < V[i].size(); j++)
    {
      if (used[i][j])
      {
        SS << V[i][j];
      }
    }
    if (i < V.size() - 1)
    {
      SS << 'A';
    }
  }
  return SS.str();
}

string erase_C(string const &S)
{
  vector<int> cnt = count(S);
  stringstream SS{};
  for (auto i = 0u; i < S.size(); i++)
  {
#if DEBUG == 1
    cerr << "SS.str() = " << SS.str() << endl;
#endif
    if (cnt[2] > cnt[1])
    {
      if (S[i] == 'C')
      {
        if (i - 1 >= 0 && i + 1 < S.size())
        {
          if ((S[i - 1] == 'A' && S[i + 1] == 'B') || (S[i - 1] == 'B' && S[i + 1] == 'A'))
          {
            cnt[2]--;
            continue;
          }
        }
        else
        {
          cnt[2]--;
          continue;
        }
      }
    }
    SS << S[i];
  }
  return SS.str();
}

string erase_AC(string const &S)
{
  vector<int> cnt = count(S);
  assert(cnt[0] <= cnt[1] && cnt[1] < cnt[2]);
  stringstream res{};
  for (auto i = 0u; i < S.size(); i++)
  {
    if (cnt[1] < cnt[2] && i < S.size() - 1 && S[i] == 'A' && S[i + 1] == 'C')
    {
      ++i;
      cnt[0]--;
      cnt[2]--;
    }
    else
    {
      res << S[i];
    }
  }
  return res.str();
}

int main()
{
  string S;
  cin >> S;
  S = reduce(S);
  map<char, char> M, R;
  M = make_map(S);
  R = make_rev(M);
  S = convert(S, M);
#if DEBUG == 1
  cerr << "S = " << S << endl;
#endif
  vector<int> cnt = count(S);
  if (cnt[1] < cnt[2])
  {
    S = erase_C(S);
#if DEBUG == 1
    cerr << "S = " << S << endl;
#endif
    cnt = count(S);
    if (cnt[1] < cnt[2])
    {
      S = erase_AC(S);
#if DEBUG == 1
      cerr << "S = " << S << endl;
#endif
    }
  }
  string ans{make_ans(S)};
#if DEBUG == 1
  cerr << "ans = " << ans << endl;
#endif
  ans = convert(ans, R);
  cout << ans << endl;
}<|endoftext|>


<commit_before>#define DEBUG 1
/**
 * File    : E.cpp
 * Author  : Kazune Takahashi
 * Created : 2019/9/7 21:38:52
 * Powered by Visual Studio Code
 */
#include <iostream>
#include <iomanip>
#include <algorithm>
#include <vector>
#include <string>
#include <complex>
#include <tuple>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <bitset>
#include <functional>
#include <random>
#include <chrono>
#include <cctype>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib>
using namespace std;
#define maxs(x, y) (x = max(x, y))
#define mins(x, y) (x = min(x, y))
using ll = long long;
class mint
{
public:
  static ll MOD;
  ll x;
  mint() : x(0) {}
  mint(ll x) : x(x % MOD) {}
  mint operator-() const { return x ? MOD - x : 0; }
  mint &operator+=(const mint &a)
  {
    if ((x += a.x) >= MOD)
    {
      x -= MOD;
    }
    return *this;
  }
  mint &operator-=(const mint &a) { return *this += -a; }
  mint &operator*=(const mint &a)
  {
    (x *= a.x) %= MOD;
    return *this;
  }
  mint &operator/=(const mint &a)
  {
    mint b{a};
    return *this *= b.power(MOD - 2);
  }
  mint operator+(const mint &a) const { return mint(*this) += a; }
  mint operator-(const mint &a) const { return mint(*this) -= a; }
  mint operator*(const mint &a) const { return mint(*this) *= a; }
  mint operator/(const mint &a) const { return mint(*this) /= a; }
  bool operator<(const mint &a) const { return x < a.x; }
  bool operator==(const mint &a) const { return x == a.x; }
  const mint power(ll N)
  {
    if (N == 0)
    {
      return 1;
    }
    else if (N % 2 == 1)
    {
      return *this * power(N - 1);
    }
    else
    {
      mint half = power(N / 2);
      return half * half;
    }
  }
};
ll mint::MOD = 1e9 + 7;
istream &operator>>(istream &stream, mint &a) { return stream >> a.x; }
ostream &operator<<(ostream &stream, const mint &a) { return stream << a.x; }
class combination
{
public:
  vector<mint> inv, fact, factinv;
  static int MAX_SIZE;
  combination() : inv(MAX_SIZE), fact(MAX_SIZE), factinv(MAX_SIZE)
  {
    inv[1] = 1;
    for (auto i = 2; i < MAX_SIZE; i++)
    {
      inv[i] = (-inv[mint::MOD % i]) * (mint::MOD / i);
    }
    fact[0] = factinv[0] = 1;
    for (auto i = 1; i < MAX_SIZE; i++)
    {
      fact[i] = mint(i) * fact[i - 1];
      factinv[i] = inv[i] * factinv[i - 1];
    }
  }
  mint operator()(int n, int k)
  {
    if (n >= 0 && k >= 0 && n - k >= 0)
    {
      return fact[n] * factinv[k] * factinv[n - k];
    }
    return 0;
  }
};
int combination::MAX_SIZE = 3000010;
ll gcd(ll x, ll y) { return y ? gcd(y, x % y) : x; }
// constexpr double epsilon = 1e-10;
// constexpr ll infty = 1000000000000000LL;
// constexpr int dx[4] = {1, 0, -1, 0};
// constexpr int dy[4] = {0, 1, 0, -1};
void Yes()
{
  cout << "Yes" << endl;
  exit(0);
}
void No()
{
  cout << "No" << endl;
  exit(0);
}

ll N;

using point = tuple<ll, ll>;

vector<vector<ll>> solve(vector<ll> const &V)
{
  vector<vector<ll>> ans(2, vector<ll>(N, -1));
  priority_queue<point, vector<point>, greater<point>> P, Q;
  for (auto i = 0LL; i < N; i++)
  {
    while (!Q.empty() && get<0>(Q.top()) < V[i])
    {
      ll val, ind;
      tie(val, ind) = Q.top();
      Q.pop();
      ans[1][ind] = i - ind;
    }
    while (!P.empty() && get<0>(P.top()) < V[i])
    {
      ll val, ind;
      tie(val, ind) = P.top();
      P.pop();
      ans[0][ind] = i - ind;
      Q.push(point(val, ind));
    }
    P.push(point(V[i], i));
  }
  for (auto i = 0; i < N; i++)
  {
    if (ans[0][i] == -1)
    {
      assert(ans[1][i] == -1);
      ans[0][i] = N - i;
      ans[1][i] = 0;
    }
    else if (ans[1][i] == -1)
    {
      ans[1][i] = N - i;
    }
    else
    {
      ans[1][i] -= ans[0][i];
    }
  }
  return ans;
}

int main()
{
  cin >> N;
  vector<ll> V(N);
  for (auto i = 0; i < N; i++)
  {
    cin >> V[i];
  }
  vector<vector<ll>> left{solve(V)};
  reverse(V.begin(), V.end());
  vector<vector<ll>> right{solve(V)};
  for (auto i = 0; i < 2; i++)
  {
    reverse(right[i].begin(), right[i].end());
  }
#if DEBUG == 1
  for (auto i = 0; i < N; i++)
  {
    cerr << "left[0][" << i << "] = " << left[0][i] << endl;
    cerr << "left[1][" << i << "] = " << left[1][i] << endl;
    cerr << "right[0][" << i << "] = " << right[0][i] << endl;
    cerr << "right[1][" << i << "] = " << right[1][i] << endl;
  }
#endif
  ll ans{0LL};
  for (auto i = 0; i < N; i++)
  {
    ans += (left[0][i] * right[1][i] + left[1][i] * right[0][i]) * V[i];
#if DEBUG == 1
    cerr << "V[" << i << "] = " << V[i] << ", " << (left[0][i] * right[1][i] + left[1][i] * right[0][i]) << endl;
#endif
  }
  cout << ans << endl;
}<commit_msg>tried E.cpp to 'E'<commit_after>#define DEBUG 1
/**
 * File    : E.cpp
 * Author  : Kazune Takahashi
 * Created : 2019/9/7 21:38:52
 * Powered by Visual Studio Code
 */
#include <iostream>
#include <iomanip>
#include <algorithm>
#include <vector>
#include <string>
#include <complex>
#include <tuple>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <bitset>
#include <functional>
#include <random>
#include <chrono>
#include <cctype>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib>
using namespace std;
#define maxs(x, y) (x = max(x, y))
#define mins(x, y) (x = min(x, y))
using ll = long long;
class mint
{
public:
  static ll MOD;
  ll x;
  mint() : x(0) {}
  mint(ll x) : x(x % MOD) {}
  mint operator-() const { return x ? MOD - x : 0; }
  mint &operator+=(const mint &a)
  {
    if ((x += a.x) >= MOD)
    {
      x -= MOD;
    }
    return *this;
  }
  mint &operator-=(const mint &a) { return *this += -a; }
  mint &operator*=(const mint &a)
  {
    (x *= a.x) %= MOD;
    return *this;
  }
  mint &operator/=(const mint &a)
  {
    mint b{a};
    return *this *= b.power(MOD - 2);
  }
  mint operator+(const mint &a) const { return mint(*this) += a; }
  mint operator-(const mint &a) const { return mint(*this) -= a; }
  mint operator*(const mint &a) const { return mint(*this) *= a; }
  mint operator/(const mint &a) const { return mint(*this) /= a; }
  bool operator<(const mint &a) const { return x < a.x; }
  bool operator==(const mint &a) const { return x == a.x; }
  const mint power(ll N)
  {
    if (N == 0)
    {
      return 1;
    }
    else if (N % 2 == 1)
    {
      return *this * power(N - 1);
    }
    else
    {
      mint half = power(N / 2);
      return half * half;
    }
  }
};
ll mint::MOD = 1e9 + 7;
istream &operator>>(istream &stream, mint &a) { return stream >> a.x; }
ostream &operator<<(ostream &stream, const mint &a) { return stream << a.x; }
class combination
{
public:
  vector<mint> inv, fact, factinv;
  static int MAX_SIZE;
  combination() : inv(MAX_SIZE), fact(MAX_SIZE), factinv(MAX_SIZE)
  {
    inv[1] = 1;
    for (auto i = 2; i < MAX_SIZE; i++)
    {
      inv[i] = (-inv[mint::MOD % i]) * (mint::MOD / i);
    }
    fact[0] = factinv[0] = 1;
    for (auto i = 1; i < MAX_SIZE; i++)
    {
      fact[i] = mint(i) * fact[i - 1];
      factinv[i] = inv[i] * factinv[i - 1];
    }
  }
  mint operator()(int n, int k)
  {
    if (n >= 0 && k >= 0 && n - k >= 0)
    {
      return fact[n] * factinv[k] * factinv[n - k];
    }
    return 0;
  }
};
int combination::MAX_SIZE = 3000010;
ll gcd(ll x, ll y) { return y ? gcd(y, x % y) : x; }
// constexpr double epsilon = 1e-10;
// constexpr ll infty = 1000000000000000LL;
// constexpr int dx[4] = {1, 0, -1, 0};
// constexpr int dy[4] = {0, 1, 0, -1};
void Yes()
{
  cout << "Yes" << endl;
  exit(0);
}
void No()
{
  cout << "No" << endl;
  exit(0);
}

ll N;

using point = tuple<ll, ll>;

vector<vector<ll>> solve(vector<ll> const &V)
{
  vector<vector<ll>> ans(2, vector<ll>(N, -1));
  priority_queue<point, vector<point>, greater<point>> P, Q;
  for (auto i = 0LL; i < N; i++)
  {
    while (!Q.empty() && get<0>(Q.top()) < V[i])
    {
      ll val, ind;
      tie(val, ind) = Q.top();
      Q.pop();
      ans[1][ind] = i - ind;
    }
    while (!P.empty() && get<0>(P.top()) < V[i])
    {
      ll val, ind;
      tie(val, ind) = P.top();
      P.pop();
      ans[0][ind] = i - ind;
      Q.push(point(val, ind));
    }
    P.push(point(V[i], i));
  }
  for (auto i = 0; i < N; i++)
  {
    if (ans[0][i] == -1)
    {
      assert(ans[1][i] == -1);
      ans[0][i] = N - i;
      ans[1][i] = 0;
    }
    else if (ans[1][i] == -1)
    {
      ans[1][i] = N - i;
    }
    else
    {
      ans[1][i] -= ans[0][i];
    }
  }
  return ans;
}

int main()
{
  cin >> N;
  vector<ll> V(N);
  for (auto i = 0; i < N; i++)
  {
    cin >> V[i];
  }
  vector<vector<ll>> left{solve(V)};
  reverse(V.begin(), V.end());
  vector<vector<ll>> right{solve(V)};
  for (auto i = 0; i < 2; i++)
  {
    reverse(right[i].begin(), right[i].end());
  }
#if DEBUG == 1
  for (auto i = 0; i < N; i++)
  {
    cerr << "left[0][" << i << "] = " << left[0][i] << endl;
    cerr << "left[1][" << i << "] = " << left[1][i] << endl;
    cerr << "right[0][" << i << "] = " << right[0][i] << endl;
    cerr << "right[1][" << i << "] = " << right[1][i] << endl;
  }
#endif
  reverse(V.begin(), V.end());
  ll ans{0LL};
  for (auto i = 0; i < N; i++)
  {
    ans += (left[0][i] * right[1][i] + left[1][i] * right[0][i]) * V[i];
#if DEBUG == 1
    cerr << "V[" << i << "] = " << V[i] << ", " << (left[0][i] * right[1][i] + left[1][i] * right[0][i]) << endl;
#endif
  }
  cout << ans << endl;
}<|endoftext|>


<commit_before>#define DEBUG 1
/**
 * File    : A.cpp
 * Author  : Kazune Takahashi
 * Created : 6/5/2020, 6:57:07 AM
 * Powered by Visual Studio Code
 */
#include <algorithm>
#include <bitset>
#include <cassert>
#include <cctype>
#include <chrono>
#include <cmath>
#include <complex>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <functional>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <tuple>
#include <unordered_map>
#include <unordered_set>
#include <vector>
// ----- boost -----
#include <boost/rational.hpp>
#include <boost/multiprecision/cpp_int.hpp>
// ----- using directives and manipulations -----
using namespace std;
using boost::rational;
using boost::multiprecision::cpp_int;
using ll = long long;
using ld = long double;
template <typename T>
using max_heap = priority_queue<T>;
template <typename T>
using min_heap = priority_queue<T, vector<T>, greater<T>>;
// ----- constexpr for Mint and Combination -----
constexpr ll MOD{1000000007LL};
// constexpr ll MOD{998244353LL}; // be careful
constexpr ll MAX_SIZE{3000010LL};
// constexpr ll MAX_SIZE{30000010LL}; // if 10^7 is needed
// ----- ch_max and ch_min -----
template <typename T>
void ch_max(T &left, T right)
{
  if (left < right)
  {
    left = right;
  }
}
template <typename T>
void ch_min(T &left, T right)
{
  if (left > right)
  {
    left = right;
  }
}
// ----- Mint -----
template <ll MOD = MOD>
class Mint
{
public:
  ll x;
  Mint() : x{0LL} {}
  Mint(ll x) : x{(x % MOD + MOD) % MOD} {}
  Mint operator-() const { return x ? MOD - x : 0; }
  Mint &operator+=(Mint const &a)
  {
    if ((x += a.x) >= MOD)
    {
      x -= MOD;
    }
    return *this;
  }
  Mint &operator-=(Mint const &a) { return *this += -a; }
  Mint &operator++() { return *this += 1; }
  Mint operator++(int)
  {
    Mint tmp{*this};
    ++*this;
    return tmp;
  }
  Mint &operator--() { return *this -= 1; }
  Mint operator--(int)
  {
    Mint tmp{*this};
    --*this;
    return tmp;
  }
  Mint &operator*=(Mint const &a)
  {
    (x *= a.x) %= MOD;
    return *this;
  }
  Mint &operator/=(Mint const &a)
  {
    Mint b{a};
    return *this *= b.power(MOD - 2);
  }
  Mint operator+(Mint const &a) const { return Mint(*this) += a; }
  Mint operator-(Mint const &a) const { return Mint(*this) -= a; }
  Mint operator*(Mint const &a) const { return Mint(*this) *= a; }
  Mint operator/(Mint const &a) const { return Mint(*this) /= a; }
  bool operator<(Mint const &a) const { return x < a.x; }
  bool operator<=(Mint const &a) const { return x <= a.x; }
  bool operator>(Mint const &a) const { return x > a.x; }
  bool operator>=(Mint const &a) const { return x >= a.x; }
  bool operator==(Mint const &a) const { return x == a.x; }
  bool operator!=(Mint const &a) const { return !(*this == a); }
  Mint power(ll N) const
  {
    if (N == 0)
    {
      return 1;
    }
    else if (N % 2 == 1)
    {
      return *this * power(N - 1);
    }
    else
    {
      Mint half = power(N / 2);
      return half * half;
    }
  }
};
template <ll MOD>
Mint<MOD> operator+(ll lhs, Mint<MOD> const &rhs)
{
  return rhs + lhs;
}
template <ll MOD>
Mint<MOD> operator-(ll lhs, Mint<MOD> const &rhs)
{
  return -rhs + lhs;
}
template <ll MOD>
Mint<MOD> operator*(ll lhs, Mint<MOD> const &rhs)
{
  return rhs * lhs;
}
template <ll MOD>
Mint<MOD> operator/(ll lhs, Mint<MOD> const &rhs)
{
  return Mint<MOD>{lhs} / rhs;
}
template <ll MOD>
istream &operator>>(istream &stream, Mint<MOD> &a)
{
  return stream >> a.x;
}
template <ll MOD>
ostream &operator<<(ostream &stream, Mint<MOD> const &a)
{
  return stream << a.x;
}
// ----- Combination -----
template <ll MOD = MOD, ll MAX_SIZE = MAX_SIZE>
class Combination
{
public:
  vector<Mint<MOD>> inv, fact, factinv;
  Combination() : inv(MAX_SIZE), fact(MAX_SIZE), factinv(MAX_SIZE)
  {
    inv[1] = 1;
    for (auto i = 2LL; i < MAX_SIZE; i++)
    {
      inv[i] = (-inv[MOD % i]) * (MOD / i);
    }
    fact[0] = factinv[0] = 1;
    for (auto i = 1LL; i < MAX_SIZE; i++)
    {
      fact[i] = Mint<MOD>(i) * fact[i - 1];
      factinv[i] = inv[i] * factinv[i - 1];
    }
  }
  Mint<MOD> operator()(int n, int k)
  {
    if (n >= 0 && k >= 0 && n - k >= 0)
    {
      return fact[n] * factinv[k] * factinv[n - k];
    }
    return 0;
  }
  Mint<MOD> catalan(int x, int y)
  {
    return (*this)(x + y, y) - (*this)(x + y, y - 1);
  }
};
// ----- for C++14 -----
using mint = Mint<MOD>;
using combination = Combination<MOD, MAX_SIZE>;
template <typename T>
T gcd(T x, T y) { return y ? gcd(y, x % y) : x; }
template <typename T>
T lcm(T x, T y) { return x / gcd(x, y) * y; }
// ----- for C++17 -----
template <typename T>
int popcount(T x) // C++20
{
  int ans{0};
  while (x != 0)
  {
    ans += x & 1;
    x >>= 1;
  }
  return ans;
}
// ----- frequently used constexpr -----
// constexpr double epsilon{1e-10};
// constexpr ll infty{1'000'000'000'000'010LL}; // or
// constexpr int infty{1'000'000'010};
// constexpr int dx[4] = {1, 0, -1, 0};
// constexpr int dy[4] = {0, 1, 0, -1};
// ----- Yes() and No() -----
void Yes()
{
  cout << "Yes" << endl;
  exit(0);
}
void No()
{
  cout << "No" << endl;
  exit(0);
}
// ----- main() -----

int main()
{
  int N;
  cin >> N;
  int cnt{0};
  for (auto i = 1; i <= N; ++i)
  {
    if (i & 1)
    {
      ++cnt;
    }
  }
  cout << fixed << setprecision(12) << static_cast<double>(cnt) / N << endl;
}
<commit_msg>submit A.cpp to 'A - Odds of Oddness' (abc142) [C++14 (GCC 5.4.1)]<commit_after>#define DEBUG 1
/**
 * File    : A.cpp
 * Author  : Kazune Takahashi
 * Created : 6/5/2020, 6:57:07 AM
 * Powered by Visual Studio Code
 */
#include <algorithm>
#include <bitset>
#include <cassert>
#include <cctype>
#include <chrono>
#include <cmath>
#include <complex>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <functional>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <tuple>
#include <unordered_map>
#include <unordered_set>
#include <vector>
// ----- boost -----
#include <boost/rational.hpp>
#include <boost/multiprecision/cpp_int.hpp>
// ----- using directives and manipulations -----
using namespace std;
using boost::rational;
using boost::multiprecision::cpp_int;
using ll = long long;
using ld = long double;
template <typename T>
using max_heap = priority_queue<T>;
template <typename T>
using min_heap = priority_queue<T, vector<T>, greater<T>>;
// ----- constexpr for Mint and Combination -----
constexpr ll MOD{1000000007LL};
// constexpr ll MOD{998244353LL}; // be careful
constexpr ll MAX_SIZE{3000010LL};
// constexpr ll MAX_SIZE{30000010LL}; // if 10^7 is needed
// ----- ch_max and ch_min -----
template <typename T>
void ch_max(T &left, T right)
{
  if (left < right)
  {
    left = right;
  }
}
template <typename T>
void ch_min(T &left, T right)
{
  if (left > right)
  {
    left = right;
  }
}
// ----- Mint -----
template <ll MOD = MOD>
class Mint
{
public:
  ll x;
  Mint() : x{0LL} {}
  Mint(ll x) : x{(x % MOD + MOD) % MOD} {}
  Mint operator-() const { return x ? MOD - x : 0; }
  Mint &operator+=(Mint const &a)
  {
    if ((x += a.x) >= MOD)
    {
      x -= MOD;
    }
    return *this;
  }
  Mint &operator-=(Mint const &a) { return *this += -a; }
  Mint &operator++() { return *this += 1; }
  Mint operator++(int)
  {
    Mint tmp{*this};
    ++*this;
    return tmp;
  }
  Mint &operator--() { return *this -= 1; }
  Mint operator--(int)
  {
    Mint tmp{*this};
    --*this;
    return tmp;
  }
  Mint &operator*=(Mint const &a)
  {
    (x *= a.x) %= MOD;
    return *this;
  }
  Mint &operator/=(Mint const &a)
  {
    Mint b{a};
    return *this *= b.power(MOD - 2);
  }
  Mint operator+(Mint const &a) const { return Mint(*this) += a; }
  Mint operator-(Mint const &a) const { return Mint(*this) -= a; }
  Mint operator*(Mint const &a) const { return Mint(*this) *= a; }
  Mint operator/(Mint const &a) const { return Mint(*this) /= a; }
  bool operator<(Mint const &a) const { return x < a.x; }
  bool operator<=(Mint const &a) const { return x <= a.x; }
  bool operator>(Mint const &a) const { return x > a.x; }
  bool operator>=(Mint const &a) const { return x >= a.x; }
  bool operator==(Mint const &a) const { return x == a.x; }
  bool operator!=(Mint const &a) const { return !(*this == a); }
  Mint power(ll N) const
  {
    if (N == 0)
    {
      return 1;
    }
    else if (N % 2 == 1)
    {
      return *this * power(N - 1);
    }
    else
    {
      Mint half = power(N / 2);
      return half * half;
    }
  }
};
template <ll MOD>
Mint<MOD> operator+(ll lhs, Mint<MOD> const &rhs)
{
  return rhs + lhs;
}
template <ll MOD>
Mint<MOD> operator-(ll lhs, Mint<MOD> const &rhs)
{
  return -rhs + lhs;
}
template <ll MOD>
Mint<MOD> operator*(ll lhs, Mint<MOD> const &rhs)
{
  return rhs * lhs;
}
template <ll MOD>
Mint<MOD> operator/(ll lhs, Mint<MOD> const &rhs)
{
  return Mint<MOD>{lhs} / rhs;
}
template <ll MOD>
istream &operator>>(istream &stream, Mint<MOD> &a)
{
  return stream >> a.x;
}
template <ll MOD>
ostream &operator<<(ostream &stream, Mint<MOD> const &a)
{
  return stream << a.x;
}
// ----- Combination -----
template <ll MOD = MOD, ll MAX_SIZE = MAX_SIZE>
class Combination
{
public:
  vector<Mint<MOD>> inv, fact, factinv;
  Combination() : inv(MAX_SIZE), fact(MAX_SIZE), factinv(MAX_SIZE)
  {
    inv[1] = 1;
    for (auto i = 2LL; i < MAX_SIZE; i++)
    {
      inv[i] = (-inv[MOD % i]) * (MOD / i);
    }
    fact[0] = factinv[0] = 1;
    for (auto i = 1LL; i < MAX_SIZE; i++)
    {
      fact[i] = Mint<MOD>(i) * fact[i - 1];
      factinv[i] = inv[i] * factinv[i - 1];
    }
  }
  Mint<MOD> operator()(int n, int k)
  {
    if (n >= 0 && k >= 0 && n - k >= 0)
    {
      return fact[n] * factinv[k] * factinv[n - k];
    }
    return 0;
  }
  Mint<MOD> catalan(int x, int y)
  {
    return (*this)(x + y, y) - (*this)(x + y, y - 1);
  }
};
// ----- for C++14 -----
using mint = Mint<MOD>;
using combination = Combination<MOD, MAX_SIZE>;
template <typename T>
T gcd(T x, T y) { return y ? gcd(y, x % y) : x; }
template <typename T>
T lcm(T x, T y) { return x / gcd(x, y) * y; }
// ----- for C++17 -----
template <typename T>
int popcount(T x) // C++20
{
  int ans{0};
  while (x != 0)
  {
    ans += x & 1;
    x >>= 1;
  }
  return ans;
}
// ----- frequently used constexpr -----
// constexpr double epsilon{1e-10};
// constexpr ll infty{1'000'000'000'000'010LL}; // or
// constexpr int infty{1'000'000'010};
// constexpr int dx[4] = {1, 0, -1, 0};
// constexpr int dy[4] = {0, 1, 0, -1};
// ----- Yes() and No() -----
void Yes()
{
  cout << "Yes" << endl;
  exit(0);
}
void No()
{
  cout << "No" << endl;
  exit(0);
}
// ----- main() -----

int main()
{
  int N;
  cin >> N;
  int cnt{0};
  for (auto i = 1; i <= N; ++i)
  {
    if (i & 1)
    {
      ++cnt;
    }
  }
  cout << fixed << setprecision(10) << static_cast<double>(cnt) / N << endl;
}
<|endoftext|>


<commit_before><commit_msg>Make logger more thread safe<commit_after><|endoftext|>


<commit_before>// Copyright (c) 2012-2013, the scalloc Project Authors.  All rights reserved.
// Please see the AUTHORS file for details.  Use of this source code is governed
// by a BSD license that can be found in the LICENSE file.

#include <gtest/gtest.h>

#include "allocators/arena.h"
#include "common.h"
#include "distributed_queue.h"
#include "runtime_vars.h"
#include "scalloc_arenas.h"

namespace {

const size_t kBackends = 80;

void* GetObject() {
  void* mem = NULL;
  if (posix_memalign(&mem, 16, 16) != 0) {
    fprintf(stderr, "posix_memalign failed\n");
    abort();
  }
  return mem;
}

DistributedQueue* InitDQ() {
  RuntimeVars::InitModule();
  scalloc::InitArenas();
  DistributedQueue::InitModule();

  static DistributedQueue dq;
  dq.Init(kBackends);
  return &dq;
}

}  // namespace

TEST(DistributedQueue, Init) {
  DistributedQueue* dq = InitDQ();
  EXPECT_TRUE(dq != NULL);
}

TEST(DistributedQueue, InitEmpty) {
  DistributedQueue* dq = InitDQ();
  EXPECT_TRUE(dq->Dequeue() == NULL);
}

TEST(DistributedQueue, EnqueueDequeue) {
  DistributedQueue* dq = InitDQ();
  void* mem = GetObject();
  dq->Enqueue(mem);
  EXPECT_EQ(dq->Dequeue(), mem);
  EXPECT_TRUE(dq->Dequeue() == NULL);
}

TEST(DistributedQueue, DequeueOnlyAt) {
  DistributedQueue* dq = InitDQ();
  void* mem = GetObject();
  dq->EnqueueAt(mem, 0);
  EXPECT_TRUE(dq->DequeueOnlyAt(1) == NULL);
  EXPECT_EQ(dq->DequeueOnlyAt(0), mem);
  EXPECT_TRUE(dq->DequeueOnlyAt(0) == NULL);
}
<commit_msg>reviewed DQ unit test<commit_after>// Copyright (c) 2012-2013, the scalloc Project Authors.  All rights reserved.
// Please see the AUTHORS file for details.  Use of this source code is governed
// by a BSD license that can be found in the LICENSE file.

#include <gtest/gtest.h>

#include "allocators/arena.h"
#include "common.h"
#include "distributed_queue.h"
#include "runtime_vars.h"
#include "scalloc_arenas.h"

namespace {

const size_t kBackends = 80;

void* GetObject() {
  void* mem = NULL;
  if (posix_memalign(&mem, 16, 16) != 0) {
    fprintf(stderr, "posix_memalign failed\n");
    abort();
  }
  return mem;
}

DistributedQueue* InitDQ() {
  RuntimeVars::InitModule();
  scalloc::InitArenas();
  DistributedQueue::InitModule();

  static DistributedQueue dq;
  dq.Init(kBackends);
  return &dq;
}

}  // namespace

TEST(DistributedQueue, Features) {
  // we cannot init the arean multiple times
  // so we put all tests together in one
  DistributedQueue* dq = InitDQ();

  // Init
  EXPECT_TRUE(dq != NULL);
  // InitEmpty
  EXPECT_TRUE(dq->Dequeue() == NULL);

  // EnqueueDequeue
  void* mem = GetObject();
  dq->Enqueue(mem);
  EXPECT_EQ(dq->Dequeue(), mem);
  EXPECT_TRUE(dq->Dequeue() == NULL);

  // DequeueOnlyAt
  mem = GetObject();
  dq->EnqueueAt(mem, 0);
  EXPECT_TRUE(dq->DequeueOnlyAt(1) == NULL);
  EXPECT_EQ(dq->DequeueOnlyAt(0), mem);
  EXPECT_TRUE(dq->DequeueOnlyAt(0) == NULL);

}

<|endoftext|>


<commit_before>#include <numeric>
#include <cmath>
#include <string>
#include "p_rect.h"
#include "algebra.h"
#include <iostream> // debug

namespace bdc {
#ifdef USE_BOX_DRAWING_CHARACTERS
	wchar_t ur = u'└'; // up and right

	wchar_t v = u'│'; // vertical

	wchar_t dr = u'┌'; // down and right

	wchar_t h = u'─'; // horizontal

	wchar_t dl = u'┐'; // down and left

	wchar_t ul = u'┘'; // up and left

	wchar_t dh = u'┬'; // down and horizontal

	wchar_t uh = u'┴'; // up and horizontal

	wchar_t vr = u'├'; // vertical and right

	wchar_t vl = u'┤'; // vertical and left

	wchar_t vh = u'┼'; // vertical and horizontal
#else
	wchar_t ur = '+';

	wchar_t v = '|';

	wchar_t dr = '+';

	wchar_t h = '-';

	wchar_t dl = '+';

	wchar_t ul = '+';

	wchar_t dh = '+';

	wchar_t uh = '+';

	wchar_t vr = '+';

	wchar_t vl = '+';

	wchar_t vh = '+';
#endif
}

template <class IMAGE_TYPE>
std::shared_ptr<IMAGE_TYPE> renderer<IMAGE_TYPE>::render(const view& v) {
	auto scn = v.scn.lock();
	auto nodes = scn->nodes();
	std::shared_ptr<IMAGE_TYPE> p_img;
	std::shared_ptr<located<IMAGE_TYPE,3>> p_located_img;
	layered_image<IMAGE_TYPE> layered_img{};

	for (auto node_ptr : nodes) {
		p_img = node_ptr->render(*this);
		auto scene_location = node_ptr->get_scene_location();
		p_located_img = std::make_shared<located<IMAGE_TYPE,3>>(*p_img,scene_location);
		layered_img.insert(p_located_img);
	}
	return layered_img.flatten_and_crop(scene_rect_to_pixel_rect(v.rectangle));
}

template <class IMAGE_TYPE>
located<rect,2> renderer<IMAGE_TYPE>::scene_rect_to_pixel_rect(located<rect,2> scene_rect) {
	int x = std::floor(scene_x_coordinate_to_pixels(scene_rect.location.x));
	int y = std::floor(scene_y_coordinate_to_pixels(scene_rect.location.y));
	int width = std::ceil(scene_x_coordinate_to_pixels(scene_rect.width));
	int height = std::ceil(scene_y_coordinate_to_pixels(scene_rect.height));
	return located<rect,2>(rect(width,height),point<2>(x,y));
}

int ascii_renderer::h_pixels_per_unit() {return p_rect::unit_size / ascii_renderer::scene_x_coordinates_per_pixel;}
int ascii_renderer::v_pixels_per_unit() {return p_rect::unit_size / ascii_renderer::scene_y_coordinates_per_pixel;}

rect ascii_renderer::pixel_dimensions(const p_rect &pr) {
	int width_in_units = pr.width_in_units();
	int height_in_units = pr.height_in_units();
	if (width_in_units == 0 || height_in_units == 0) {
		return rect(0,0);
	}
	return rect(ascii_renderer::h_pixels_per_unit() * width_in_units + 1, ascii_renderer::v_pixels_per_unit() * height_in_units + 1);
}

// the x pixel coordinates of all vertical partitions, including left and right boundaries
std::vector<int> x_partitions(const p_rect &pr) {
	std::vector<int> output{};
	if (ascii_renderer::pixel_dimensions(pr).width == 0) {
		return output;
	}
	int x = 0;
	output.push_back(x);
	for (length l : pr.x_lengths) {
		x += l.val * ascii_renderer::h_pixels_per_unit();
		output.push_back(x);
	}
	return output;
}

// the y pixel coordinates of all horizontal partitions, including top and bottom boundaries
std::vector<int> y_partitions(const p_rect &pr) {
	std::vector<int> output{};
	if (ascii_renderer::pixel_dimensions(pr).width == 0) {
		return output;
	}
	int y = 0;
	output.push_back(y);
	for (length l : pr.y_lengths) {
		y += l.val * ascii_renderer::v_pixels_per_unit();
		output.push_back(y);
	}
	return output;
}

template <class T, class OutputIt>
void copy(T t, OutputIt first, OutputIt last) {
	for (auto it = first; it != last; ++it) {
		*it = t;
	}
}

void draw_h_lines(const p_rect &pr, std::shared_ptr<ascii_image> img) {
	rect dim = ascii_renderer::pixel_dimensions(pr);
	for (int y : y_partitions(pr)) {
		// draw a horizontal line at y
		pixel_range<wchar_t> range{img,0,y,dim.width,y + 1};
		copy(bdc::h,range.begin(),range.end());
	}
}

void draw_v_lines(const p_rect &pr, std::shared_ptr<ascii_image> img) {
	rect dim = ascii_renderer::pixel_dimensions(pr);
	for (int x : x_partitions(pr)) {
		// draw a vertical line at x
		pixel_range<wchar_t> range{img,x,0,x + 1,dim.height};
		copy(bdc::v,range.begin(),range.end());
	}
}

void draw_interior_intersections(const p_rect &pr, std::shared_ptr<ascii_image> img) {
	for (int x : x_partitions(pr)) {
		for (int y : y_partitions(pr)) {
			img->pixel_at(x,y) = bdc::vh;
		}
	}
}

void draw_top_and_bottom_intersections(const p_rect &pr, std::shared_ptr<ascii_image> img) {
	rect dim = ascii_renderer::pixel_dimensions(pr);
	for (int x : x_partitions(pr)) {
		img->pixel_at(x,0) = bdc::uh;
		img->pixel_at(x,dim.height - 1) = bdc::dh;
	}
}

void draw_left_and_right_intersections(const p_rect &pr, std::shared_ptr<ascii_image> img) {
	rect dim = ascii_renderer::pixel_dimensions(pr);
	for (int y : y_partitions(pr)) {
		img->pixel_at(0, y) = bdc::vr;
		img->pixel_at(dim.width - 1, y) = bdc::vl;
	}
}

void draw_corners(const p_rect &pr, std::shared_ptr<ascii_image> img) {
	rect dim = ascii_renderer::pixel_dimensions(pr);
	img->pixel_at(0,0) = bdc::ur;
	img->pixel_at(0,dim.height - 1) = bdc::dr;
	img->pixel_at(dim.width - 1, 0) = bdc::ul;
	img->pixel_at(dim.width - 1, dim.height - 1) = bdc::dl;
}

void draw_labels(const p_rect &pr, std::shared_ptr<ascii_image> img) {
	int left = 0;  // leftmost x-coordinate of current cell
	int bottom = 0;  // bottom y-coordinate of current cell
	for (auto x_len : pr.x_lengths) {
		for (auto y_len : pr.y_lengths) {
			std::string label = algebra::product_to_string(x_len.name, y_len.name);
			int label_y = bottom +(y_len.val * ascii_renderer::v_pixels_per_unit() / 2);
			int label_x = left + (x_len.val * ascii_renderer::h_pixels_per_unit() / 2) - (int) (label.size() / 2);

			pixel_range<wchar_t> range{img,label_x,label_y,static_cast<int>(label_x + label.size()),label_y + 1};
			std::copy(label.begin(),label.end(),range.begin());

			bottom += y_len.val * ascii_renderer::v_pixels_per_unit();
		}
		left += x_len.val * ascii_renderer::h_pixels_per_unit();
		bottom = 0;
	}
}

std::shared_ptr<ascii_image> ascii_renderer::render(const p_rect &pr) {
	rect dim = pixel_dimensions(pr);
	auto output = std::make_shared<ascii_image>(dim);
	if (dim.width == 0) {
		return output;
	}

	draw_h_lines(pr,output);
	draw_v_lines(pr,output);
	draw_interior_intersections(pr,output);
	draw_left_and_right_intersections(pr,output);
	draw_top_and_bottom_intersections(pr,output);
	draw_corners(pr,output);
	draw_labels(pr,output);
	return output;
}

// explicit instantiations
template class renderer<ascii_image>;
<commit_msg>render only  views associated with scenes and nodes that are renderable<commit_after>#include <numeric>
#include <cmath>
#include <string>
#include "p_rect.h"
#include "algebra.h"
#include <iostream> // debug

namespace bdc {
#ifdef USE_BOX_DRAWING_CHARACTERS
	wchar_t ur = u'└'; // up and right

	wchar_t v = u'│'; // vertical

	wchar_t dr = u'┌'; // down and right

	wchar_t h = u'─'; // horizontal

	wchar_t dl = u'┐'; // down and left

	wchar_t ul = u'┘'; // up and left

	wchar_t dh = u'┬'; // down and horizontal

	wchar_t uh = u'┴'; // up and horizontal

	wchar_t vr = u'├'; // vertical and right

	wchar_t vl = u'┤'; // vertical and left

	wchar_t vh = u'┼'; // vertical and horizontal
#else
	wchar_t ur = '+';

	wchar_t v = '|';

	wchar_t dr = '+';

	wchar_t h = '-';

	wchar_t dl = '+';

	wchar_t ul = '+';

	wchar_t dh = '+';

	wchar_t uh = '+';

	wchar_t vr = '+';

	wchar_t vl = '+';

	wchar_t vh = '+';
#endif
}

template <class IMAGE_TYPE>
std::shared_ptr<IMAGE_TYPE> renderer<IMAGE_TYPE>::render(const view& v) {
	auto scn_ = v.scn.lock();
	if (!scn_) {return std::make_shared<located<IMAGE_TYPE,3>>();}
	auto nodes = scn_->nodes();
	std::shared_ptr<IMAGE_TYPE> p_img;
	std::shared_ptr<located<IMAGE_TYPE,3>> p_located_img;
	layered_image<IMAGE_TYPE> layered_img{};

	for (auto node_ptr : nodes) {
		if (node_ptr->is_renderable()) {
			p_img = node_ptr->render(*this);
			auto scene_location = node_ptr->get_scene_location();
			p_located_img = std::make_shared<located<IMAGE_TYPE,3>>(*p_img,scene_location);
			layered_img.insert(p_located_img);
		}
	}
	return layered_img.flatten_and_crop(scene_rect_to_pixel_rect(v.rectangle));
}

template <class IMAGE_TYPE>
located<rect,2> renderer<IMAGE_TYPE>::scene_rect_to_pixel_rect(located<rect,2> scene_rect) {
	int x = std::floor(scene_x_coordinate_to_pixels(scene_rect.location.x));
	int y = std::floor(scene_y_coordinate_to_pixels(scene_rect.location.y));
	int width = std::ceil(scene_x_coordinate_to_pixels(scene_rect.width));
	int height = std::ceil(scene_y_coordinate_to_pixels(scene_rect.height));
	return located<rect,2>(rect(width,height),point<2>(x,y));
}

int ascii_renderer::h_pixels_per_unit() {return p_rect::unit_size / ascii_renderer::scene_x_coordinates_per_pixel;}
int ascii_renderer::v_pixels_per_unit() {return p_rect::unit_size / ascii_renderer::scene_y_coordinates_per_pixel;}

rect ascii_renderer::pixel_dimensions(const p_rect &pr) {
	int width_in_units = pr.width_in_units();
	int height_in_units = pr.height_in_units();
	if (width_in_units == 0 || height_in_units == 0) {
		return rect(0,0);
	}
	return rect(ascii_renderer::h_pixels_per_unit() * width_in_units + 1, ascii_renderer::v_pixels_per_unit() * height_in_units + 1);
}

// the x pixel coordinates of all vertical partitions, including left and right boundaries
std::vector<int> x_partitions(const p_rect &pr) {
	std::vector<int> output{};
	if (ascii_renderer::pixel_dimensions(pr).width == 0) {
		return output;
	}
	int x = 0;
	output.push_back(x);
	for (length l : pr.x_lengths) {
		x += l.val * ascii_renderer::h_pixels_per_unit();
		output.push_back(x);
	}
	return output;
}

// the y pixel coordinates of all horizontal partitions, including top and bottom boundaries
std::vector<int> y_partitions(const p_rect &pr) {
	std::vector<int> output{};
	if (ascii_renderer::pixel_dimensions(pr).width == 0) {
		return output;
	}
	int y = 0;
	output.push_back(y);
	for (length l : pr.y_lengths) {
		y += l.val * ascii_renderer::v_pixels_per_unit();
		output.push_back(y);
	}
	return output;
}

template <class T, class OutputIt>
void copy(T t, OutputIt first, OutputIt last) {
	for (auto it = first; it != last; ++it) {
		*it = t;
	}
}

void draw_h_lines(const p_rect &pr, std::shared_ptr<ascii_image> img) {
	rect dim = ascii_renderer::pixel_dimensions(pr);
	for (int y : y_partitions(pr)) {
		// draw a horizontal line at y
		pixel_range<wchar_t> range{img,0,y,dim.width,y + 1};
		copy(bdc::h,range.begin(),range.end());
	}
}

void draw_v_lines(const p_rect &pr, std::shared_ptr<ascii_image> img) {
	rect dim = ascii_renderer::pixel_dimensions(pr);
	for (int x : x_partitions(pr)) {
		// draw a vertical line at x
		pixel_range<wchar_t> range{img,x,0,x + 1,dim.height};
		copy(bdc::v,range.begin(),range.end());
	}
}

void draw_interior_intersections(const p_rect &pr, std::shared_ptr<ascii_image> img) {
	for (int x : x_partitions(pr)) {
		for (int y : y_partitions(pr)) {
			img->pixel_at(x,y) = bdc::vh;
		}
	}
}

void draw_top_and_bottom_intersections(const p_rect &pr, std::shared_ptr<ascii_image> img) {
	rect dim = ascii_renderer::pixel_dimensions(pr);
	for (int x : x_partitions(pr)) {
		img->pixel_at(x,0) = bdc::uh;
		img->pixel_at(x,dim.height - 1) = bdc::dh;
	}
}

void draw_left_and_right_intersections(const p_rect &pr, std::shared_ptr<ascii_image> img) {
	rect dim = ascii_renderer::pixel_dimensions(pr);
	for (int y : y_partitions(pr)) {
		img->pixel_at(0, y) = bdc::vr;
		img->pixel_at(dim.width - 1, y) = bdc::vl;
	}
}

void draw_corners(const p_rect &pr, std::shared_ptr<ascii_image> img) {
	rect dim = ascii_renderer::pixel_dimensions(pr);
	img->pixel_at(0,0) = bdc::ur;
	img->pixel_at(0,dim.height - 1) = bdc::dr;
	img->pixel_at(dim.width - 1, 0) = bdc::ul;
	img->pixel_at(dim.width - 1, dim.height - 1) = bdc::dl;
}

void draw_labels(const p_rect &pr, std::shared_ptr<ascii_image> img) {
	int left = 0;  // leftmost x-coordinate of current cell
	int bottom = 0;  // bottom y-coordinate of current cell
	for (auto x_len : pr.x_lengths) {
		for (auto y_len : pr.y_lengths) {
			std::string label = algebra::product_to_string(x_len.name, y_len.name);
			int label_y = bottom +(y_len.val * ascii_renderer::v_pixels_per_unit() / 2);
			int label_x = left + (x_len.val * ascii_renderer::h_pixels_per_unit() / 2) - (int) (label.size() / 2);

			pixel_range<wchar_t> range{img,label_x,label_y,static_cast<int>(label_x + label.size()),label_y + 1};
			std::copy(label.begin(),label.end(),range.begin());

			bottom += y_len.val * ascii_renderer::v_pixels_per_unit();
		}
		left += x_len.val * ascii_renderer::h_pixels_per_unit();
		bottom = 0;
	}
}

std::shared_ptr<ascii_image> ascii_renderer::render(const p_rect &pr) {
	rect dim = pixel_dimensions(pr);
	auto output = std::make_shared<ascii_image>(dim);
	if (dim.width == 0) {
		return output;
	}

	draw_h_lines(pr,output);
	draw_v_lines(pr,output);
	draw_interior_intersections(pr,output);
	draw_left_and_right_intersections(pr,output);
	draw_top_and_bottom_intersections(pr,output);
	draw_corners(pr,output);
	draw_labels(pr,output);
	return output;
}

// explicit instantiations
template class renderer<ascii_image>;
<|endoftext|>