#include<bits/stdc++.h>
using namespace std;
#define int long long
#define in array<int, 2>
#define pb push_back
#define pob pop_back
#define fast() ios_base::sync_with_stdio(false); cin.tie(NULL)
const int MX = 2e3+5;
const int INF = 2e18;
struct ndata
{
int L, R, S, T;
};
ndata create(int x)
{
ndata ret;
ret.L = ret.R = ret.S = max(x, 0ll);
ret.T = x;
return ret;
}
void rev(ndata &d)
{
swap(d.L, d.R);
return;
}
ndata merge(const ndata &d1, const ndata &d2)
{
ndata d3;
d3.L = max(d1.L, d1.T + d2.L);
d3.R = max(d2.R, d2.T + d1.R);
d3.S = max(max(d1.S, d2.S), d1.R + d2.L);
d3.T = d1.T + d2.T;
return d3;
}
struct seg_tree
{
vector<ndata> tree;
void build(const vector<int> &a, int id, int l, int r)
{
int m = (l+r)/2;
if(l == r)
{
tree[id] = create(a[m]);
return;
}
build(a, 2*id, l, m);
build(a, 2*id+1, m+1, r);
tree[id] = merge(tree[2*id], tree[2*id+1]);
return;
}
void init(int n, const vector<int> &a)
{
tree.resize(4*n+50);
build(a, 1, 1, n);
return;
}
void upd(int p, int val, int id, int l, int r)
{
if(l == r)
{
tree[id] = create(val);
return;
}
int m = (l+r)/2;
if(p <= m)
upd(p, val, 2*id, l, m);
else
upd(p, val, 2*id+1, m+1, r);
tree[id] = merge(tree[2*id], tree[2*id+1]);
return;
}
int Q()
{
return tree[1].S;
}
};
in sloppy(in pt1, in pt2)
{
in zz = {pt1[1]-pt2[1], pt1[0]-pt2[0]};
if(zz[1] < 0)
{
zz[1] = -zz[1];
zz[0] = -zz[0];
}
if(zz[1] == 0)
return {1, 0};
int g = __gcd(abs(zz[1]), abs(zz[0]));
zz[1]/=g;
zz[0]/=g;
return zz;
}
bool comp(array<int, 4> s1, array<int, 4> s2)
{
int XX = s1[0]*s2[1];
int YY = s2[0]*s1[1];
if(XX < YY)
return true;
if(XX > YY)
return false;
return (((in){s1[3], s1[4]}) < ((in){s2[3], s2[4]}));
}
int dot(in x1, in x2)
{
return x1[0]*x2[0] - x1[1]*x2[1];
}
signed main()
{
fast();
int n; cin >> n;
vector<in> pt(n+1);
vector<int> w(n+1);
for(int i = 1; i <= n; i++)
cin >> pt[i][0] >> pt[i][1] >> w[i];
if(n == 1)
{
cout << max(w[1], 0ll) << "\n";
return 0;
}
vector<array<int, 4>> GG;
for(int i = 1; i <= n; i++)
{
for(int j = i+1; j <= n; j++)
{
auto [x, y] = sloppy(pt[i], pt[j]);
GG.pb({x, y, i, j});
}
}
sort(GG.begin(), GG.end(), comp);
vector<vector<in>> ff;
in lst = {-1, -1};
in st = {GG[0][0], GG[0][1]};
for(auto [x, y, i, j]: GG)
{
//cout << x << " " << y << endl;
if(((in){x, y}) == lst)
ff.back().pb({i, j});
else
{
ff.pb({{i, j}});
lst = {x, y};
}
}
/*for(auto s: ff)
{
cout << "Next set: " << endl;
for(auto [i, j]: s)
cout << pt[i][0] << " " << pt[i][1] << " " << pt[j][0] << " " << pt[j][1] << endl;
}*/
vector<int> where(n+1);
vector<in> srt(n+1);
for(int i = 1; i <= n; i++)
srt[i] = {dot(pt[i], st), i};
sort(srt.begin()+1, srt.end());
vector<int> s(n+1);
for(int i = 1; i <= n; i++)
{
s[i] = w[srt[i][1]];
where[srt[i][1]] = i;
}
seg_tree work;
work.init(n, s);
int ANS = work.Q();
//cout << st[0] << " " << st[1] << endl;
for(auto T: ff)
{
//cout << "Current perm " << endl;
vector<int> WTF(n+1);
/*for(int i = 1; i <= n; i++)
WTF[where[i]] = i;
for(int i = 1; i <= n; i++)
cout << WTF[i] << " ";
cout << endl;*/
for(auto [i, j]: T)
{
work.upd(where[i], w[j], 1, 1, n);
work.upd(where[j], w[i], 1, 1, n);
swap(where[i], where[j]);
//assert(abs(where[i]-where[j]) == 1);
}
ANS = max(ANS, work.Q());
}
cout << ANS << "\n";
return 0;
}
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |