teamnote default

This commit is contained in:
2026-06-03 09:20:51 +09:00
commit f50ed902fe
65 changed files with 6033 additions and 0 deletions

View File

@@ -0,0 +1,60 @@
struct ray
{
ll x, y, dx, dy; int i, j;
ray(pll A, pll B, int i = 0, int j = 0)
{
if(A.fi == B.fi && A.se > B.se) swap(A, B), swap(i, j);
if(A.fi>B.fi) swap(A, B), swap(i, j);
this->i = i; this->j = j;
x = A.fi; y = A.se;
dx = B.fi-A.fi; dy = B.se-A.se;
}
friend bool operator<(const ray& A, const ray& B)
{
return (A.dy*B.dx == B.dy*A.dx)?A.x == B.x?A.dx<B.dx:A.x<B.x:(A.dy*B.dx < B.dy*A.dx);
}
};
const int N = 1005;
vector<pair<pll, int> > p; vector<ray> vec;
int num[N];
void solve()
{
getint(n);
p.pb({{0, 0}, 0});
forr(i, n)
{
getll(a); getll(b); getchar(c);
p.pb({{a, b}, c=='R'});
}
sort(p.begin()+1, p.end());
forr(i, n) num[i] = i;
Seg s(1, n, p);
forr(i, n) fors(j, i+1, n) vec.pb(ray(p[i].fi, p[j].fi, i, j));
sort(all(vec));
ll ans = s.query(1, n).m;
for(auto r:vec)
{
int i = r.i, j = r.j;
assert(num[i]+1 == num[j]);
int ii = p[num[i]].se;
int jj = p[num[j]].se;
//printf("%d %d %d %d\n", i, j, ii, jj);
s.update(num[j], [ii](Dta A){return Dta(ii);});
//printf("%d\n", s.query(1, n).m);
s.update(num[i], [jj](Dta A){return Dta(jj);});
//printf("%d\n", s.query(1, n).m);
swap(p[num[i]], p[num[j]]);
swap(num[i], num[j]);
ans = max(ans, (ll)s.query(1, n).m);
}
printf("%lld\n", ans);
}

26
source/Geometry/Geo.cpp Normal file
View File

@@ -0,0 +1,26 @@
forr(i, now) vec.pb(A[i]);
sort(all(vec));
vll upper;
for(auto i:vec)
{
while(upper.size() >= 2 && ccw(upper[upper.size()-2], upper.back(), i) >= 0)
upper.pop_back();
upper.push_back(i);
}
reverse(all(vec));
vll lower;
for(auto i:vec)
{
while(lower.size() >= 2 && ccw(lower[lower.size()-2], lower.back(), i) >= 0)
lower.pop_back();
lower.push_back(i);
}
assert(upper.front() == lower.back() && lower.front() == upper.back());
upper.pop_back(); lower.pop_back();
vll hull;
hull.insert(hull.end(), all(upper));
hull.insert(hull.end(), all(lower));

50
source/Geometry/HPI.cpp Normal file
View File

@@ -0,0 +1,50 @@
using ld = long double;
using pdd = pair<ld, ld>;
using line = pair<pdd, pdd>; // half plane : left side of vector fi->se
const ld eps = 1e-9;
pdd operator*(const pdd& a, ld s) { return {a.fi * s, a.se * s}; }
inline bool equals(ld a, ld b) { return abs(a - b) < eps; }
bool line_intersect(line& a, line& b, pdd& v) {
ld det = (a.se - a.fi) / (b.se - b.fi);
if (equals(det, 0)) return 0;
ld t = ((b.fi - a.fi) / (b.se - b.fi)) / det;
v = a.fi + (a.se - a.fi) * t;
return 1;
}
bool bad(line& a, line& b, line& c) {
pdd v; if(!line_intersect(a, b, v)) return 0;
return (c.se - c.fi) / (v - c.fi) <= eps;
}
vector<pdd> HPI(vector<line>& lns) {
auto lsgn = [&](const line& a) {
if(a.fi.se == a.se.se) return a.fi.fi > a.se.fi;
return a.fi.se > a.se.se;
};
sort(lns.begin(), lns.end(), [&](const line& a, const line& b) {
if(lsgn(a) != lsgn(b)) return lsgn(a) < lsgn(b);
return (a.se - a.fi) / (b.se - b.fi) > 0;
});
deque<line> dq;
for(auto l : lns){
while(dq.size() >= 2 && bad(dq[dq.size()-2], dq.back(), l)) dq.pop_back();
while(dq.size() >= 2 && bad(dq[0], dq[1], l)) dq.pop_front();
if(dq.size() < 2 || !bad(dq.back(), l, dq[0])) dq.pb(l);
}
vector<pdd> res;
if(dq.size() >= 3) {
for(int i = 0; i < (int)dq.size(); i++) {
int j = (i + 1) % (int)dq.size();
pdd v;
if(!line_intersect(dq[i], dq[j], v)) continue;
res.push_back(v);
}
}
return res;
}

View File

@@ -0,0 +1,47 @@
using pii=pair<int,int>;
pii operator+(pii A, pii B){return {A.fi+B.fi, A.se+B.se};}
pii operator-(pii A, pii B){return {A.fi-B.fi, A.se-B.se};}
ll operator*(pii A, pii B){return (ll)A.fi*B.fi+(ll)A.se*B.se;} // inner product
ll operator/(pii A, pii B){return (ll)A.fi*B.se-(ll)A.se*B.fi;} // outer product
// 각도 정렬 (O = pii(0, 0))
sort(P+1, P+1+n, [](pii A, pii B) {
if(B == O) return false;
if(A == O) return true;
return (A<O)!=(B<O)?A>B:A/B<0;
});
// 선분 교차
// Segment : fi에서 시작하는 se 벡터
// fi + k * se, 0 <= k <= 1
using Segment = pair<pii, pii>;
int isJoin(const Segment& A, const Segment& B) {
if(B.se/A.se != 0) {
ll p = (A.fi-B.fi)/A.se;
ll q = B.se/A.se;
if(q<0) q = -q, p = -p;
if(p < 0 or p > q) return false;
p = (B.fi-A.fi)/B.se;
q = A.se/B.se;
if(q<0) q = -q, p = -p;
if(p < 0 or p > q) return false;
return true;
}
else {
if((A.fi-B.fi)/A.se != 0) return false;
ll p = A.fi*A.se, q = (A.fi+A.se)*A.se;
ll r = B.fi*A.se, s = (B.fi+B.se)*A.se;
if(p>q) swap(p, q); if(r>s) swap(r, s);
if(max(p, r) > min(q, s)) return false;
return true;
}
}

View File

@@ -0,0 +1,16 @@
auto isunder = [](pii upper[], int u, pii x, bool inv = false){ // inv==true : isover
int r = inv?-1:1;
int idx = lower_bound(upper+1, upper+1+u, x,
[&r](pii a, pii b){return r*a.fi<r*b.fi;}) - upper;
if(idx > u) return false;
if(idx == 1) {
if(r*x.fi < r*upper[1].fi) return false;
else {
int h = upper[1].se;
if(upper[2].fi == upper[1].fi) h = upper[2].se;
return r*x.se <= r*h;
}
}
return ccw(upper[idx-1], upper[idx], x) <= 0;
};

View File

@@ -0,0 +1,163 @@
typedef pair<ll, ll> pll;
#define _x first
#define _y second
pll operator-(const pll &a, const pll &b){
return {a._x - b._x, a._y - b._y};
}
ll cross(const pll &a, const pll &b){
return a._x * b._y - b._x * a._y;
}
ll dot(const pll &a, const pll &b){
return a._x * b._x + a._y * b._y;
}
int ccw(const pll &p1, const pll &p2, const pll &p3){
ll res = cross(p2 - p1, p3 - p1);
return (res != 0) * (res < 0 ? -1 : 1);
}
// dist of point - point
double dist(const pll &p1, const pll &p2){
return sqrt((p1._x - p2._x) * (p1._x - p2._x) + (p1._y - p2._y) * (p1._y - p2._y));
}
// dist of line - point
double dist(const pll &l1, const pll &l2, const pll &p){
ll area = abs(cross(l2 - l1, p - l1));
return area / dist(l1, l2);
}
// dist of seg - point
double segDist(P& s, P& e, P& p) {
if (s==e) return (p-s).dist();
auto d = (e-s).dist2(), t = min(d,max(.0,(p-s).dot(e-s)));
return ((p-s)*d-(e-s)*t).dist()/d;
}
P perp() const { return P(-y, x); } // rotates +90 degrees
int sgn(T x) { return (x > 0) - (x < 0); } // sign of x
// Returns where p is as seen from s towards e. 1/0/-1 <-> left/on line/right.
int sideOf(P s, P e, P p) { return sgn(s.cross(e, p)); }
// Returns a vector of either 0, 1, or 2 intersection points.
template<class P>
vector<P> circleLine(P c, double r, P a, P b) {
P ab = b - a, p = a + ab * (c-a).dot(ab) / ab.dist2();
double s = a.cross(b, c), h2 = r*r - s*s / ab.dist2();
if (h2 < 0) return {};
if (h2 == 0) return {p};
P h = ab.unit() * sqrt(h2);
return {p - h, p + h};
}
// Computes the pair of points at which two circles intersect.
typedef Point<double> P;
bool circleInter(P a,P b,double r1,double r2,pair<P, P>* out) {
if (a == b) { assert(r1 != r2); return false; }
P vec = b - a;
double d2 = vec.dist2(), sum = r1+r2, dif = r1-r2,
p = (d2 + r1*r1 - r2*r2)/(d2*2), h2 = r1*r1 - p*p*d2;
if (sum*sum < d2 || dif*dif > d2) return false;
P mid = a + vec*p, per = vec.perp() * sqrt(fmax(0, h2) / d2);
*out = {mid + per, mid - per};
return true;
}
// Returns true iff p lies on the line segment from s to e.
template<class P> bool onSegment(P s, P e, P p) {
return p.cross(s, e) == 0 && (s - p).dot(e - p) <= 0;
}
// Circumcircle
typedef Point<double> P;
double ccRadius(const P& A, const P& B, const P& C) {
return (B-A).dist()*(C-B).dist()*(A-C).dist()/
abs((B-A).cross(C-A))/2;
}
P ccCenter(const P& A, const P& B, const P& C) {
P b = C-A, c = B-A;
return A + (b*c.dist2()-c*b.dist2()).perp()/b.cross(c)/2;
}
// Minimum enclosing circle
pair<P, double> mec(vector<P> ps) {
shuffle(all(ps), mt19937(time(0)));
P o = ps[0];
double r = 0, EPS = 1 + 1e-8;
rep(i,0,sz(ps)) if ((o - ps[i]).dist() > r * EPS) {
o = ps[i], r = 0;
rep(j,0,i) if ((o - ps[j]).dist() > r * EPS) {
o = (ps[i] + ps[j]) / 2;
r = (o - ps[i]).dist();
rep(k,0,j) if ((o - ps[k]).dist() > r * EPS) {
o = ccCenter(ps[i], ps[j], ps[k]);
r = (o - ps[i]).dist();
}
}
}
return {o, r};
}
// point inside convex hull in logN
bool inHull(const vector<P>& l, P p, bool strict = true) {
int a = 1, b = sz(l) - 1, r = !strict;
if (sz(l) < 3) return r && onSegment(l[0], l.back(), p);
if (sideOf(l[0], l[a], l[b]) > 0) swap(a, b);
if (sideOf(l[0], l[a], p) >= r || sideOf(l[0], l[b], p)<= -r)
return false;
while (abs(a - b) > 1) {
int c = (a + b) / 2;
(sideOf(l[0], l[c], p) > 0 ? b : a) = c;
}
return sgn(l[a].cross(l[b], p)) < r;
}
// convex hull
vector<pll> convex_hull(vector<pii> &arr){
vector<pll> up, down;
for(auto p : arr){
while(up.size() >= 2 && ccw(up[up.size() - 2], up[up.size() - 1], p) >= 0) up.pop_back();
while(down.size() >= 2 && ccw(down[down.size() - 2], down[down.size() - 1], p) <= 0) down.pop_back();
up.push_back(p);
down.push_back(p);
}
up.insert(up.end(), down.rbegin() + 1, down.rend());
return up;
}
// rotating callipers
typedef Point<ll> P;
array<P, 2> hullDiameter(vector<P> S) {
int n = sz(S), j = n < 2 ? 0 : 1;
pair<ll, array<P, 2>> res({0, {S[0], S[0]}});
rep(i,0,j)
for (;; j = (j + 1) % n) {
res = max(res, {(S[i] - S[j]).dist2(), {S[i], S[j]}});
if ((S[(j + 1) % n] - S[j]).cross(S[i + 1] - S[i]) >= 0)
break;
}
return res.second;
}
// Closest pair
typedef Point<ll> P;
pair<P, P> closest(vector<P> v) {
assert(sz(v) > 1);
set<P> S;
sort(all(v), [](P a, P b) { return a.y < b.y; });
pair<ll, pair<P, P>> ret{LLONG_MAX, {P(), P()}};
int j = 0;
for (P p : v) {
P d{1 + (ll)sqrt(ret.first), 0};
while (v[j].y <= p.y - d.x) S.erase(v[j++]);
auto lo = S.lower_bound(p - d), hi = S.upper_bound(p + d);
for (; lo != hi; ++lo)
ret = min(ret, {(*lo - p).dist2(), {*lo, p}});
S.insert(p);
}
return ret.second;
}

View File

@@ -0,0 +1,109 @@
template <typename T>
class Point {
public:
T x, y;
Point() : x(0), y(0) {};
Point(T _x, T _y) : x(_x), y(_y) {};
Point operator+(Point p2){
return Point(x + p2.x, y + p2.y);
}
Point operator-(Point p2){
return Point(x - p2.x, y - p2.y);
}
T operator*(Point p2){
return x * p2.x + y * p2.y;
}
T operator/(Point p2) {
return x * p2.y - p2.x * y;
}
T operator==(Point p2) {
return (x == p2.x) && (y == p2.y);
}
T sqdist() {
return x*x + y*y;
}
bool operator<(Point p2) {
if(y == p2.y)
return x < p2.x;
return y < p2.y;
}
};
namespace geometry {
template <typename T>
ll ccw(Point<T> center, Point<T> p2, Point<T> p3) {
ll res = (p2 - center) / (p3 - center);
return (res > 0) - (res < 0);
}
template <typename T>
double theta(Point<T> center, Point<T> p2, Point<T> p3) {
return acos(p2 * p3 / sqrt(p2.sqdist() * p3.sqdist()));
}
template <typename T>
function<bool(Point<T> &, Point<T> &, Point<T>)> cmp_point = [](Point<T> &l, Point<T> &r, Point<T> O = {(T)0, (T)0}) -> bool {
return (l < O) != (r < O) ? l < r : l/r > 0;
};
template <typename T>
T sq_dist(Point<T> &p1, Point<T> &p2) {
return (p2.x - p1.x)*(p2.x - p1.x) + (p2.y - p1.y)*(p2.y - p1.y);
}
template <typename T>
double dist(Point<T> &p1, Point<T> &p2) {
return sqrt((double)sq_dist(p1, p2));
}
template <typename T>
double line_point_dist(pair<Point<T>, Point<T>> &l, Point<T> p)
{
Point<T> p1 = p - l.first, p2 = l.second - l.first;
return abs(p1 / p2)/(dist(l.first, l.second));
}
template <typename T>
double line_min_dist(pair<Point<T>, Point<T>> &l1, pair<Point<T>, Point<T>> &l2) {
double ans = INFINITY;
ans = min({ans, dist(l1.first, l2.first), dist(l1.first, l2.second), dist(l1.second, l2.first), dist(l1.second, l2.second)});
if((l1.second - l1.first)*(l2.first - l1.first) > 0 && (l1.first - l1.second)*(l2.first - l1.second) > 0)
ans = min({ans, line_point_dist<double>(l1, l2.first)});
if((l1.second - l1.first)*(l2.second - l1.first) > 0 && (l1.first - l1.second)*(l2.second - l1.second) > 0)
ans = min({ans, line_point_dist<double>(l1, l2.second)});
swap(l1, l2);
if((l1.second - l1.first)*(l2.first - l1.first) > 0 && (l1.first - l1.second)*(l2.first - l1.second) > 0)
ans = min({ans, line_point_dist<double>(l1, l2.first)});
if((l1.second - l1.first)*(l2.second - l1.first) > 0 && (l1.first - l1.second)*(l2.second - l1.second) > 0)
ans = min({ans, line_point_dist<double>(l1, l2.second)});
swap(l1, l2);
return ans;
}
template <typename T>
vector<T> convex_hull(vector<Point<T>> &pts) {
assert(pts.size() >= 2);
vector<Point<T>> res;
swap(pts[0], *min_element(pts.begin(), pts.end()));
sort(pts.begin()+1, pts.end(), [&pts](Point<T> &a, Point<T> &b){
ll cw = ccw(pts[0], a, b);
if(cw) return cw > 0;
return sq_dist(pts[0], a) < sq_dist(pts[0], b);
});
auto itr = pts.begin();
res.push_back(*(itr++)); res.push_back(*(itr++));
while(itr != pts.end())
{
while(res.size() >= 2 && ccw(res[res.size()-2], res[res.size()-1], *itr) <= 0)
res.pop_back();
res.push_back(*(itr++));
}
return res;
}
}
using namespace geometry;