제출 #1129245

#제출 시각아이디문제언어결과실행 시간메모리
1129245mircea_007Mixture (BOI20_mixture)C++20
0 / 100
1 ms328 KiB
#include <stdio.h>
#include <ctype.h>

int nextc() {
  int ch;
  while( isspace( ch = fgetc( stdin ) ) );
  return ch;
}

#include <algorithm>
#include <vector>
#include <set>

using ll = long long;
struct Rat {
  // conditie extra: b este mereu pozitiv
  ll a, b;
  Rat( ll a = 0, ll b = 1 ): a(a), b(b) {}
  Rat operator - () const { return Rat(-a, b); }

  Rat operator + ( const Rat& that ) const { return Rat(a * that.b + b * that.a, b * that.b); }
  Rat operator - ( const Rat& that ) const { return *this + (-that); }

  Rat operator += ( const Rat& that ) { return *this = *this + that; }
  Rat operator -= ( const Rat& that ) { return *this = *this - that; }

  bool operator == ( const Rat& that ) const { return a * (__int128)that.b == that.a * (__int128)b; }
};

struct Point {
  // conditie extra: x.b == y.b mereu
  Rat x, y;
  Point( Rat x, Rat y ): x(x), y(y) {}
  Point( int S, int P, int G ): x(S, S + P + G), y(P, S + P + G) {}
  Point operator - () const { return Point(-x, -y); }

  Point operator + ( const Point& that ) const { return Point(x + that.x, y + that.y); }
  Point operator - ( const Point& that ) const { return Point(x - that.x, y - that.y); }

  Point operator += ( const Point& that ) { return *this = *this + that; }
  Point operator -= ( const Point& that ) { return *this = *this - that; }

  bool operator == ( const Point& that ) const { return x == that.x && y == that.y; }

  // 1 0
  // 2 3
  int cadran() const {
    bool neg_x = (x.a < 0), neg_y = (y.a < 0);
    return (neg_x ^ neg_y) + 2 * neg_y;
  }

  // sortare trigonometrica
  bool operator < ( const Point& that ) const {
    int cthis = cadran(), cthat = that.cadran();
    if( cthis != cthat )
      return cthis < cthat;

    return that.y.a * (__int128)x.a > y.a * (__int128)that.x.a; // 'determinant cu originea'
  }
};

bool is_big( const Point& a, const Point& b ) {
  if( a.cadran() < 2 )
    return b < a || (-a) < b;
  else
    return b < a && (-a) < b;
}

Point read_point() {
  int S, P, G;
  scanf( "%d%d%d", &S, &P, &G );
  return Point(S, P, G);
}

struct OriginMixture {
  int origin_freq;

  std::multiset<Point> angles;
  int plusminus; // cate perechi unghiuri opuse avem?
  int big_angles; // diferente > PI

  std::vector<Point> insertions;

  OriginMixture(): origin_freq(0), angles(), plusminus(0), big_angles(0), insertions() {}
  int min_mixture() {
    if( origin_freq )
      return 1;
    if( plusminus )
      return 2;
    if( (int)angles.size() >= 2 && !big_angles )
      return 3;

    return 0;
  }

  void insert( Point P ) {
    insertions.push_back( P );

    // inseram originea?
    if( P == Point(Rat(0), Rat(0)) ){
      origin_freq++;
      return;
    }

    // primul inserat?
    if( (int)angles.size() == 0 ){
      angles.insert( P );
      return;
    }

    // inseram panta
    bool plus = (angles.find( P ) != angles.end());
    bool minus = (angles.find( -P ) != angles.end());

    if( !plus && minus )
      plusminus++;

    if( plus )
      return;

    auto prev_it = angles.lower_bound( P );
    if( prev_it == angles.begin() )
      prev_it = angles.end();
    prev_it--;

    auto next_it = angles.upper_bound( P );
    if( next_it == angles.end() )
      next_it = angles.begin();

    big_angles -= is_big( *prev_it, *next_it );
    big_angles += is_big( *prev_it, P );
    big_angles += is_big( P, *next_it );

    angles.insert( P );
  }

  void erase( int idx ) {
    Point P = insertions[idx];

    // scoatem originea?
    if( P == Point(Rat(0), Rat(0)) ){
      origin_freq--;
      return;
    }

    // ultimum scos?
    if( (int)angles.size() == 1 ){
      angles.erase( angles.find( P ) );
      return;
    }

    // scoatem panta
    angles.erase( angles.find( P ) ); // activitati obisnuite multiset

    bool plus = (angles.find( P ) != angles.end());
    bool minus = (angles.find( -P ) != angles.end());

    if( !plus && minus )
      plusminus--;

    if( plus )
      return;

    auto prev_it = angles.lower_bound( P );
    if( prev_it == angles.begin() )
      prev_it = angles.end();
    prev_it--;

    auto next_it = angles.upper_bound( P );
    if( next_it == angles.end() )
      next_it = angles.begin();

    big_angles -= is_big( *prev_it, P );
    big_angles -= is_big( P, *next_it );
    big_angles += is_big( *prev_it, *next_it );
  }
};

int main() {
  Point origin = read_point();

  OriginMixture mix;

  int ops;
  for( scanf( "%d", &ops ); ops--; ){
    char task = nextc();

    if( task == 'A' )
      mix.insert( read_point() - origin );
    else{
      int idx;
      scanf( "%d", &idx );
      idx--;

      mix.erase( idx );
    }

    printf( "%d\n", mix.min_mixture() );
  }
  
  return 0;
}

컴파일 시 표준 에러 (stderr) 메시지

Mixture.cpp: In function 'Point read_point()':
Mixture.cpp:71:8: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
   71 |   scanf( "%d%d%d", &S, &P, &G );
      |   ~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
Mixture.cpp: In function 'int main()':
Mixture.cpp:185:13: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
  185 |   for( scanf( "%d", &ops ); ops--; ){
      |        ~~~~~^~~~~~~~~~~~~~
Mixture.cpp:192:12: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
  192 |       scanf( "%d", &idx );
      |       ~~~~~^~~~~~~~~~~~~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...