claris的题解很详细
总结:
把区间不等关系写成前缀和形式----化成两点的不等
(x,y,z)三元组任意一维不等,则可以一维排序,一维树状数组,查询不同色的最大值、最小值
一开始感觉代码很乱,不知道自己的实现是否有错。
其实逻辑非常清楚,需要注意的只有变量名
还有为了防止下标<=0,加上n + 10,如果刚好+n会有=0的下标。
#include
using namespace std;
#define rep(i,l,r) for(register int i = l ; i <= r ; i++)
#define repd(i,r,l) for(register int i = r ; i >= l ; i--)
#define rvc(i,S) for(register int i = 0 ; i < (int)S.size() ; i++)
#define rvcd(i,S) for(register int i = ((int)S.size()) - 1 ; i >= 0 ; i--)
#define fore(i,x)for (register int i = head[x] ; i ; i = e[i].next)
#define forup(i,l,r) for (register int i = l ; i <= r ; i += lowbit(i))
#define fordown(i,id) for (register int i = id ; i ; i -= lowbit(i))
#define pb push_back
#define prev prev_
#define stack stack_
#define mp make_pair
#define fi first
#define se second
#define lowbit(x) ((x)&(-(x)))
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
typedef pair<int,int> pr;
const int maxn = 1e6 + 20;
const int inf = 1e9;
int mx_id[2][maxn * 2],mn[2][maxn * 2],mn2[2][maxn * 2],mx[2][maxn * 2],mx2[2][maxn * 2],mn_id[2][maxn * 2];
int a[220];
int n,ans,cnt[maxn][3];
char ch[maxn];
struct node{
int a,b,c,id;
bool operator < (node x)const{
return a < x.a;
}
}dt[maxn];
inline int query(int t,int pos,int c,int id){
if ( pos <= 0 ) return 0;
int l = inf , r = 0;
fordown(i,pos){
if ( mx_id[t][i] == c ){
r = max(r,mx2[t][i]);
}
else r = max(r,mx[t][i]);
if ( mn_id[t][i] == c ){
l = min(l,mn2[t][i]);
}
else l = min(l,mn[t][i]);
}
// cout<
return max(0,max(id - l,r - id));
}
inline void modify(int t,int pos,node x){
forup(i,pos,n * 2 + 10){
if ( mx[t][i] < x.id ){
if ( mx_id[t][i] != x.c ) mx2[t][i] = mx[t][i];
mx_id[t][i] = x.c , mx[t][i] = x.id;
}
else if ( mx2[t][i] < x.id && x.c != mx_id[t][i] ){
mx2[t][i] = x.id;
}
if ( mn[t][i] > x.id ){
if ( mn_id[t][i] != x.c ) mn2[t][i] = mn[t][i];
mn_id[t][i] = x.c , mn[t][i] = x.id;
}
else if ( mn2[t][i] > x.id && x.c != mn_id[t][i] ){
mn2[t][i] = x.id;
}
}
}
int main(){
scanf("%d%s",&n,ch + 1);
n = strlen(ch + 1);
a['B'] = 0 , a['C'] = 1 , a['S'] = 2;
dt[0] = (node){0,0,0,0};
rep(i,1,n){
rep(k,0,2) cnt[i][k] = cnt[i - 1][k] + (a[ch[i]] == k);
int a = cnt[i][0] - cnt[i][1] , b = cnt[i][1] - cnt[i][2] , c = cnt[i][2] - cnt[i][0];
dt[i] = (node){a,b,c,i};
}
rep(i,1,n * 2 + 10) rep(t,0,1) mn[t][i] = mn2[t][i] = inf;
sort(dt,dt + n + 1);
int last = 0;
// cout<<"dt : \n";
// rep(i,0,n) cout<
rep(i,0,n){
if ( i && dt[i].a != dt[i - 1].a ){
rep(j,last,i - 1){
modify(0,dt[j].b + n + 10,dt[j]);
modify(1,n - dt[j].b + 10,dt[j]);
}
last = i;
}
ans = max(ans,query(0,dt[i].b - 1 + n + 10,dt[i].c,dt[i].id));
ans = max(ans,query(1,n - dt[i].b - 1 + 10,dt[i].c,dt[i].id));
}
// rep(j,last,n){
// ans = max(ans,query(0,dt[j].b - 1 + n,dt[j].c,dt[j].id));
// ans = max(ans,query(1,n - dt[j].b - 1,dt[j].c,dt[j].id));
// }
int p = 1;
rep(i,1,n){
if ( ch[p] != ch[i] ) p = i;
ans = max(ans,i - p + 1);
}
cout<<ans<<endl;
}
感觉这套题很水,但是没有发现很多trick,被题目绕进去了,比如那道数论,真不知道这个结论
2019.3.18
直接贪心就好
注意根据奇偶性特判不可达位置
一开始把题意读错了,如果任给一些区间做障碍物这道题更有意思
做法是首先把高度变成x + h,这样就不用下降(好想)。还可以把坐标除/2,这样可达变成了连续的,不用考虑奇偶性。
然后维护每个横坐标的可达区间,横坐标加就是整体shift(右端点右移)。用堆和set维护第一个R和L相撞
加入一个不可达区间相当于加入两个端点
结论:a∗Bk≡a(mod B−1)
所以最多只会删除一位,a[i] >= 1
直接二分前缀和
奇数乘2可以发现增长到1e9是log级别的
偶数取mex相当于每次mex加一(遇到已有的数跳过)
当偶数>1e9就对mex没有任何影响。所以暴力跑出小数的差,用map存起来,其他数只可能是相邻的偶-奇,二分一下
不能盲目的打表
要从递推式本身出发找性质。关联数据范围。
一开始只知道打表什么都没有发现,看了题解才想到,很不应该!
#include
using namespace std;
#define rep(i,l,r) for(register int i = l ; i <= r ; i++)
#define repd(i,r,l) for(register int i = r ; i >= l ; i--)
#define rvc(i,S) for(register int i = 0 ; i < (int)S.size() ; i++)
#define rvcd(i,S) for(register int i = ((int)S.size()) - 1 ; i >= 0 ; i--)
#define fore(i,x)for (register int i = head[x] ; i ; i = e[i].next)
#define forup(i,l,r) for (register int i = l ; i <= r ; i += lowbit(i))
#define fordown(i,id) for (register int i = id ; i ; i -= lowbit(i))
#define pb push_back
#define prev prev_
#define stack stack_
#define mp make_pair
#define fi first
#define se second
#define lowbit(x) ((x)&(-(x)))
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
typedef pair<int,int> pr;
const int inf = 1e9;
const int N = 3e6 + 10;
const int maxn = 100020;
const ll mod = 1e9 + 7;
int a[maxn];
int n,tot,cnt,b[maxn];
map <int,int> vis;
map <int,pr> dt;
int getmex(int n){
vis.clear();
rep(i,1,n){
rep(j,1,i - 1){
int x = abs(a[i] - a[j]);
vis[x] = 1;
}
}
int res = 1;
while ( vis[res]) res++;
return res;
}
void init(){
a[1] = 1 , a[2] = 2;
rep(i,3,1000){
if ( i & 1 ) a[i] = a[i - 1] * 2;
else{
a[i] = a[i - 1] + getmex(i - 1);
if ( a[i] > inf ){ tot = i; break; }
}
}
rep(i,1,tot) rep(j,1,i - 1){
dt[a[i] - a[j]] = mp(i,j);
b[++cnt] = a[i] - a[j];
}
sort(b + 1,b + cnt + 1);
// rep(i,1,cnt) cout<
}
void solve(){
int x;
scanf("%d",&x);
if ( dt.find(x) != dt.end() ) printf("%d %d\n",dt[x].fi,dt[x].se);
else{
int c = lower_bound(b + 1,b + cnt + 1,x) - b - 1;
printf("%d %d\n",tot + (x - c) * 2,tot + (x - c) * 2 - 1);
}
}
int main(){
init();
scanf("%d",&n);
while ( n-- ){
solve();
}
}
显然背叛叶子最劣
然后是一个简单的树形DP。当前点的最大比例=max(min(f[son],sz[son] / (sz[x] - 1))
一开始以为二分,根本没有想DP。
然后T飞、首先bzoj根本不知道有多少组数据。
这道题应该是一个很显然的树形DP,没有立即反应过来。还需要积累!
竞赛图讲解
竞赛图一定存在哈密顿路径
强连通则有哈密顿回路
tarjian后在DAG上求最长路
板子写了1小时,对代码的实现能力不够,还需要提高
#include
using namespace std;
#define rep(i,l,r) for(register int i = l ; i <= r ; i++)
#define repd(i,r,l) for(register int i = r ; i >= l ; i--)
#define rvc(i,S) for(register int i = 0 ; i < (int)S.size() ; i++)
#define rvcd(i,S) for(register int i = ((int)S.size()) - 1 ; i >= 0 ; i--)
#define fore(i,x)for (register int i = head[x] ; i ; i = e[i].next)
#define forup(i,l,r) for (register int i = l ; i <= r ; i += lowbit(i))
#define fordown(i,id) for (register int i = id ; i ; i -= lowbit(i))
#define pb push_back
#define prev prev_
#define stack stack_
#define mp make_pair
#define fi first
#define se second
#define lowbit(x) ((x)&(-(x)))
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
typedef pair<int,int> pr;
const ld inf = 2e18;
const int N = 3e6 + 10;
const int maxn = 2020;
const ll mod = 1e9 + 7;
int e[maxn][maxn];
int n;
int dfn[maxn],low[maxn],ins[maxn],st[maxn],tops,belong[maxn],tot,sz[maxn],dfstime;
int nxt[maxn][maxn],hh[maxn],tt[maxn];
int f[maxn],to[maxn];
vector <int> vec[maxn],P;
void clear(){
rep(i,1,n){
vec[i].clear();
belong[i] = sz[i] = ins[i] = dfn[i] = low[i] = hh[i] = tt[i] = 0;
}
rep(i,1,n) rep(j,1,n) nxt[i][j] = 0;
tops = dfstime = tot = 0;
}
void getpath(int nxt[],int &head,int &tail,const vector <int> &V){
//找哈密顿路径
head = tail = V[0];
nxt[head] = 0;
rep(i,1,V.size() - 1){
int cur = V[i];
if ( e[tail][cur] ) nxt[tail] = cur , tail = cur , nxt[cur] = 0;
else if ( e[cur][head] ) nxt[cur] = head , head = cur;
else{
for (int x = head ; x ; x = nxt[x]){
if ( e[x][cur] && e[cur][nxt[x]] ){
nxt[cur] = nxt[x] , nxt[x] = cur;
break;
}
}
}
}
if ( head == tail ){
nxt[tail] = head;
return;
}
//找哈密顿回路
//找最靠右的和head相连的节点
int id = 0;
for (int x = nxt[head] ; x ; x = nxt[x]){
if ( e[x][head] ) id = x;
}
tail = id , P.clear();
for (int x = nxt[id] ; x ; x = nxt[x]){
P.pb(x);
}
if ( !P.size() ){
nxt[tail] = head;
return;
}
nxt[id] = 0;
int pre = P[0];
//从这个环开始扩大
rvc(i,P){
int cur = P[i],flag = 0;
if ( !pre ) pre = cur;
for (int x = head ; x ; x = nxt[x]){
if ( e[x][pre] && e[cur][nxt[x]] ){
nxt[cur] = nxt[x];
nxt[x] = pre;
flag = 1 , pre = 0;
break;
}
}
// if ( !flag ){
// if ( pre != cur ) nxt[P[i - 1]] = P[i];
// }
}
nxt[tail] = head;
}
void print_Path(int c){
printf("%d ",hh[c]);
for (int x = nxt[c][hh[c]] ; x != hh[c] ; x = nxt[c][x]){
printf("%d ",x);
}
}
void print_Path(int c,int y){
printf("%d ",y);
for (int x = nxt[c][y] ; x != y ; x = nxt[c][x]){
printf("%d ",x);
}
}
void dfs(int x){
low[x] = dfn[x] = ++dfstime;
st[++tops] = x , ins[x] = 1;
// fore(i,x){
rep(i,1,n){
if ( !e[x][i] ) continue;
if ( !dfn[i] ){
dfs(i);
low[x] = min(low[x],low[i]);
}
else if ( ins[i] ){
low[x] = min(low[x],dfn[i]);
}
}
if ( low[x] == dfn[x] ){
++tot;
int s = st[tops--];
while ( x != s){
sz[tot]++ , belong[s] = tot , ins[s] = 0;
vec[tot].pb(s);
s = st[tops--];
}
vec[tot].pb(x);
sz[tot]++ , belong[x] = tot , ins[x] = 0;
getpath(nxt[tot],hh[tot],tt[tot],vec[tot]);
// print_Path(tot);
}
}
void solve(){
rep(i,1,tot){
rvc(j,vec[i]){
rep(k,1,n){
if ( !e[vec[i][j]][k] ) continue;
int c = belong[k];
if ( c == i ) continue;
if ( f[c] > f[i] ){
f[i] = f[c];
to[i] = c;
}
}
}
f[i] += sz[i];
}
rep(i,1,n){
int c = belong[i];
printf("%d ",f[c]);
int x = c;
print_Path(x,i) , x = to[x];
while ( x ) print_Path(x) , x = to[x];
puts("");
}
}
int main(){
// freopen("input.txt","r",stdin);
scanf("%d",&n);
rep(i,2,n){
rep(j,1,i - 1){
int x;
scanf("%d",&x);
if ( x ) e[j][i] = 1;
else e[i][j] = 1;
}
}
rep(i,1,n) if ( !dfn[i] ) dfs(i);
solve();
}
题目不是很难,但是细节真的很多。要完全自己全部理清楚需要细致的思维。
从上午10点到12点,下午16点到晚上19点只写了4道题,效率太低了!
2019.3.13
Description
给定一个n行m列的矩阵,请对于每个长宽均为k的连续子正方形,统计里面出现过的数值的种类数。
Input
第一行包含三个正整数n,m,k(n,m<=3000,k<=min(n,m))。
接下来n行,每行m个正整数a[i]j,表示矩阵中每个位置的数值。
题解
分开考虑每个颜色,每一个点对一个K∗K的正方形有贡献,但同一种颜色的贡献至多为1。
从上到下扫描矩阵,我们需要维护一些正方形的进入和删除。
由于正方形边长固定,每次贡献实际产生变化的是一个区间。
用线段树支持前驱后继的查找即可确定产生变化的区间。
每处理完一行,用差分+前缀和统计本行的答案。(所有颜色一起扫描线,直接可以计算答案)
时间复杂度O(N∗M∗LogM)。
总结
关于二维的差分要想清楚,为了只统计一次,每个矩形只统计最靠左,然后是最靠上的。
然后发现每个点的贡献区域是一个下凸东西,这东西不能维护。
不能想当然认为直接差分就好!
直接用矩形面积并的模型。但因为边长相同可以简化
代码还没有写
听说bzoj卡常
Description
定义一个区间(l,r)的长度为r-l,空区间的长度为0。
给定数轴上n个区间,请选择其中恰好k个区间,使得交集的长度最大。
Input
第一行包含两个正整数n,k(1<=k<=n<=1000000),表示区间的数量。
接下来n行,每行两个正整数l,r(1<=l
题解
假如我们已经确定了最终区间的左端点L,那么我们选择的区间一定是左端点在L左边,且右端点最右的K个点。所以我们将所有区间按左端点排序,用小根堆维护左端点在左边,且右端点最大的K个点。每次用第K大值更新答案即可。
总结
这道题很简单,但是一开始把看错了,看成求并了----这个可以wqs二分?
求交的话就是固定一个端点统计。
这样最优解一定会被统计到
Description
在地面上有一个水箱,它的俯视图被划分成了n行m列个方格,相邻两个方格之间有一堵厚度可以忽略不计的墙,水
箱与外界之间有一堵高度无穷大的墙,因此水不可能漏到外面。已知水箱内每个格子的高度都是[0,H]之间的整数
,请统计有多少可能的水位情况。因为答案可能很大,请对10^9+7取模输出。两个情况不同当且仅当存在至少一个
方格的水位在两个情况中不同。
Input
第一行包含三个正整数n,m,H(n*m<=500000,1<=H<=10^9)。
接下来n行,每行m-1个整数a[i]j,表示(i,j)和(i,j+1)之间的墙的高度。
接下来n-1行,每行m个整数b[i]j,表示(i,j)和(i+1,j)之间的墙的高度。
题解
按高度从小到大排序,每次加入相当于合并两个联通块。增加的这个高度对每个联通块来说块内的水位相同。合并后把各自的方案数乘起来(因为在水位<=当前高度时,两块互不干扰)
用并查集维护
Description
有一棵n个点的无根树,每条边有一个正整数权值,表示长度,定义两点距离为在树上的最短路径的长度。
已知2到n-1每个点在树上与1和n的距离,请根据这些信息还原出这棵树。
Input
第一行包含一个正整数n(2<=n<=500000),表示点数。
第二行包含n-2个正整数d(1,2),d(1,3),…,d(1,n-1),分别表示每个点到1的距离。
第三行包含n-2个正整数d(n,2),d(n,3),…,d(n,n-1),分别表示每个点到n的距离。
输入数据保证1<=d<=1000000。
题解(来自cz_xuyixuan)
分别考虑1和N之间是否有边直接相连。
若有边相连,所有到1和N距离的差值的绝对值应该相等。
否则,到1和N距离的和的最小值就是1到N的距离,将这条链构造出来,将其它点逐一挂在上面即可。
时间复杂度O(N+D)。
总结:
一开始忘了判1-N的连边,一直WA。
然后为了简便直接开距离那么大的vector,忘了乘2.
调了很久,大概1个多小时,本来是非常简单的题,但是细节注意的很不好
一定要想清楚再写!
把代码贴上来警醒自己!
#include
using namespace std;
#define rep(i,l,r) for(register int i = l ; i <= r ; i++)
#define repd(i,r,l) for(register int i = r ; i >= l ; i--)
#define rvc(i,S) for(register int i = 0 ; i < (int)S.size() ; i++)
#define rvcd(i,S) for(register int i = ((int)S.size()) - 1 ; i >= 0 ; i--)
#define fore(i,x)for (register int i = head[x] ; i ; i = e[i].next)
#define forup(i,l,r) for (register int i = l ; i <= r ; i += lowbit(i))
#define fordown(i,id) for (register int i = id ; i ; i -= lowbit(i))
#define pb push_back
#define prev prev_
#define stack stack_
#define mp make_pair
#define fi first
#define se second
#define lowbit(x) ((x)&(-(x)))
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
typedef pair<int,int> pr;
const int inf = 2e8;
const int N = 2e6 + 10;
const int maxn = 500020;
const ll mod = 1e9 + 7;
struct node{
int next,to,w,from;
}e[maxn * 2];
int head[maxn],cnt;
int fa[maxn],dth[maxn];
int n,m;
pr dis[maxn];
vector <int> vec[N];
inline void adde(int x,int y,int w){
// cout<
if ( w <= 0 )return;
e[++cnt].to = y;
e[cnt].from = x;
e[cnt].next = head[x];
e[cnt].w = w;
head[x] = cnt;
}
bool cmp(int x,int y){
return (dis[x].fi + dis[x].se) < (dis[y].fi + dis[y].se);
}
void dfs(int x,int fa){
fore(i,x){
if ( e[i].to == fa ) continue;
dth[e[i].to] = dth[x] + e[i].w;
dfs(e[i].to,x);
}
}
bool check(){
rep(i,1,n) dth[i] = 0;
dfs(1,0);
rep(i,1,n) if ( dis[i].fi != dth[i] ) return 0;
rep(i,1,n) dth[i] = 0;
dfs(n,0);
rep(i,1,n) if ( dis[i].se != dth[i] ) return 0;
return 1;
}
bool check2(){
int d = abs(dis[2].fi - dis[2].se);
if ( !d ) return 0;
rep(i,2,n - 1) if ( abs(dis[i].fi - dis[i].se) != d ) return 0;
puts("TAK");
printf("%d %d %d\n",1,n,d);
rep(i,2,n - 1){
if ( dis[i].fi < dis[i].se ) printf("%d %d %d\n",i,1,dis[i].fi);
else printf("%d %d %d\n",i,n,dis[i].se);
}
return 1;
}
int main(){
// freopen("input.txt","r",stdin);
scanf("%d",&n);
if ( n == 2 ){
cout<<"TAK\n";
cout<<"1 2 1\n";
return 0;
}
rep(i,2,n - 1) scanf("%d",&dis[i].fi);
rep(i,2,n - 1) scanf("%d",&dis[i].se);
if ( check2() ){
return 0;
}
m = inf;
rep(i,2,n - 1) m = min(m,dis[i].fi + dis[i].se);
dis[1] = mp(0,m) , dis[n] = mp(m,0);
rep(i,1,n){
int d = (dis[i].fi + dis[i].se - m) / 2;
if ( dis[i].fi - d >= 0 ) vec[dis[i].fi - d].pb(i);
}
int last = 0,lastd = 0;
rep(i,0,m){
if ( !vec[i].size() ) continue;
sort(vec[i].begin(),vec[i].end(),cmp);
// cout<<" dist : "<
// rvc(j,vec[i]) cout<
if ( last ) adde(last,vec[i][0],dis[vec[i][0]].fi - lastd) , adde(vec[i][0],last,dis[vec[i][0]].fi - lastd);
last = vec[i][0] , lastd = dis[vec[i][0]].fi;
int id = 0;
rep(j,1,vec[i].size() - 1){
int w = ((dis[vec[i][j]].fi + dis[vec[i][j]].se) - (dis[vec[i][id]].fi + dis[vec[i][id]].se)) / 2;
adde(vec[i][id],vec[i][j],w);
adde(vec[i][j],vec[i][id],w);
}
vec[i].clear();
}
if ( check() ){
puts("TAK");
for (int i = 1 ; i <= cnt ; i += 2){
printf("%d %d %d\n",e[i].from,e[i].to,e[i].w);
}
}
else puts("NIE");
}
Description
在无限大的二维平面的原点(0,0)放置着一个棋子。你有n条可用的移动指令,每条指令可以用一个二维整数向量表
示。每条指令最多只能执行一次,但你可以随意更改它们的执行顺序。棋子可以重复经过同一个点,两条指令的方
向向量也可能相同。你的目标是让棋子最终离原点的欧几里得距离最远,请问这个最远距离是多少?
Input
第一行包含一个正整数n(n<=200000),表示指令条数。
接下来n行,每行两个整数x,y(|x|,|y|<=10000),表示你可以从(a,b)移动到(a+x,b+y)。
题解
这题没有想出来,连极角排序都没有想到,很不应该
对向量的性质很不敏感啊
确定了答案向量的方向,只会选投影在此方向为正的向量。
并且,选择的向量一定是一个连续的区间
那么,极角排序,twopointers扫一遍,使得当前指针和当前向量的夹角<180
注意扫描过程中要边扫边更新答案
总结
很多细节:
1. 极角排序的时候在坐标范围小的时候老老实实用atan2(预选计算好角度)
2. 要记得当r < i时更新指针
3. 边扫边计算答案
4. 直接用atan2算角度,非常方便,扫一圈以后+2pi即可
5. 最后先把0,0判掉
6. 如果用叉积判角度要注意共线的情况,先把同向共线去掉(如果用atan2不用)。反向共线要用点积辅助判。很麻烦
还是不知道我的按照象限极角排序为什么有问题
#include
using namespace std;
#define rep(i,l,r) for(register int i = l ; i <= r ; i++)
#define repd(i,r,l) for(register int i = r ; i >= l ; i--)
#define rvc(i,S) for(register int i = 0 ; i < (int)S.size() ; i++)
#define rvcd(i,S) for(register int i = ((int)S.size()) - 1 ; i >= 0 ; i--)
#define fore(i,x)for (register int i = head[x] ; i ; i = e[i].next)
#define forup(i,l,r) for (register int i = l ; i <= r ; i += lowbit(i))
#define fordown(i,id) for (register int i = id ; i ; i -= lowbit(i))
#define pb push_back
#define prev prev_
#define stack stack_
#define mp make_pair
#define fi first
#define se second
#define lowbit(x) ((x)&(-(x)))
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
typedef pair<int,int> pr;
const int inf = 2e8;
const int N = 3e6 + 10;
const int maxn = 1000020;
const ll mod = 1e9 + 7;
const double eps = 1e-7;
const double pi = acos(-1.0);
struct point{
int x,y,k;
double ang;
point operator + (point a){
return (point){x + a.x,y + a.y,0,ang};
}
}dt[maxn],dt2[maxn];
int n,tot;
ll ans;
inline int quadrant(point a){
if ( a.x >= 0 && a.y > 0 ) return 1;
if ( a.x < 0 && a.y >= 0 ) return 2;
if ( a.x <= 0 && a.y < 0 ) return 3;
return 4;
// if ( a.x > 0 && a.y <= 0 ) return 4;
}
inline int det(point a,point b){
return a.x * b.y - a.y * b.x;
}
inline int dot(point a,point b){
return a.x * b.x + a.y * b.y;
}
inline int sgn(double x){
if ( abs(x) < eps ) return 0;
return x > 0 ? 1 : -1;
}
bool cmp(point a,point b){
// int ka = quadrant(a) , kb = quadrant(b);
// if ( a.k == b.k ){
// return det(a,b) > 0;
// }
// return a.k < b.k;
return a.ang < b.ang;
}
int main(){
// freopen("input.txt","r",stdin);
scanf("%d",&n);
rep(i,1,n){
scanf("%d %d",&dt[i].x,&dt[i].y),dt[i].k = quadrant(dt[i]),dt[i].ang = atan2(dt[i].y,dt[i].x);
if ( !dt[i].x && !dt[i].y ){ i--; n--; }
}
sort(dt + 1,dt + n + 1,cmp);
// rep(i,1,n) cout<
/* rep(i,1,n){
if ( tot && det(dt[i],dt2[tot]) == 0 && dot(dt[i],dt2[tot]) > 0 ) dt2[tot] = dt[i] + dt2[tot];
else dt2[++tot] = dt[i];
}*/
// rep(i,1,tot) dt[i] = dt2[i];
// n = tot;
rep(i,1,n) dt[i + n] = dt[i] , dt[i + n].ang += pi * 2;
int r = 1; ll sx = dt[1].x , sy = dt[1].y;
rep(i,1,n){
if ( r < i ){
sx = dt[i].x , sy = dt[i].y , r = i;
}
ans = max(ans,(ll)sx * sx + (ll)sy*sy);
//(det(dt[i],dt[r + 1]) > 0 || (det(dt[i],dt[r + 1]) == 0 && dot(dt[i],dt[r + 1] ) < 0))
while ( r < n + i - 1 && sgn(dt[r + 1].ang - dt[i].ang - pi) <= 0 ) ++r , sx += dt[r].x , sy += dt[r].y, ans = max(ans,(ll)sx * sx + (ll)sy*sy);;
//ans = max(ans,(ll)sx * sx + (ll)sy*sy);
sx -= dt[i].x , sy -= dt[i].y;
}
cout<<ans<<endl;
}