A组
题目
矮人排队
Time Limits: 1000 ms
Memory Limits: 32768 KB
Description
在七山七海之外的一个小村庄,白雪公主与N个矮人住在一起,所有时间都花在吃和玩League of Legend游戏。白雪公主决心终结这样的生活,所以为他们举办了体育课。 在每节课开始时,矮人必须按他们的身高站队。假定矮人们有高度1,2,…,N(每个人高度互不相同)。然而,由于不健康的生活方式,矮人的智力有所恶化,所以他们没有能力依照自己的高度排序。
因此,白雪公主发出以下形式命令帮助他们:
1 X Y:X和Y位置的矮人互换位置。
2 A B:询问高度为A,A+1,…, B的矮人(不一定是按照这个顺序)是否已形成了当前队列的连续子序列。
帮助矮人按照白雪公主的指示行动,并回答她的问题。
Input
输入的第一行包含两个正整数N和M,分别表示矮人的数量和白雪公主的命令数,2≤N≤200,000,2≤M≤200,000。
第二行包含N个用空格隔开的从1到N的正整数,每个数只出现一次,代表矮人的初始排列。
接下来的M行包含白雪公主的命令,形式为“1 X Y”(1≤X,Y≤N,X≠Y)或“2 A B”(1≤A≤B≤N)。
Output
对于每个命令2输出“YES”或“NO”。
Sample Input
输入1:
5 3
2 4 1 3 5
2 2 5
1 3 1
2 2 5
输入2:
7 7
4 7 3 5 1 2 6
2 1 7
1 3 7
2 4 6
2 4 7
2 1 4
1 1 4
2 1 4
Sample Output
输出1:
NO
YES
输出2:
YES
NO
YES
NO
YES
Data Constraint
50%的数据:类型2询问中A,B满足B−A≤50B-A≤50B−A≤50
间谍派遣
Time Limits: 1000 ms
Memory Limits: 32768 KB
Description
你是M,一个雇佣N个标号为从1到N的间谍的情报机关的总管。每个间谍被派往不同的国家并在那获取重要情报。
如下是你的任务:
- 在部分间谍间组织会面。每次会面在两个间谍间进行,两个间谍交换他们自己获取的或从之前会面中得到的信息。因为在不同国家的两个间谍间组织机密会面很困难,所以每次秘密会面都有一个费用。
- 当所有会面结束后,选择一部分间谍参加拯救世界的任务。一个间谍k参加此项任务需要花费Mk。很重要的一点是,任务要成功,必须满足参加任务的间谍获取的情报聚集到一起包含了其他剩余间谍所有的信息。
请找出完成任务的最小花费,即组织会面和派遣间谍的费用之和。
Input
输入的第一行包含正整数N,表示间谍数目(2≤N≤10002≤N≤10002≤N≤1000)。
接下来的N行包含N个不超过10610^6106的非负整数。在k行m列的数字表示间谍k和m间会面的花费,同样的,与m行k列的数字相等,k=m时数字为0。
接下来的一行包含N个正整数MkM_kMk(1≤Mk≤1061≤M_k≤10^61≤Mk≤106),分别为派遣间谍1,2,…,N参加任务的花费。
Output
只有一行,为所需的最小总费用。
Sample Input
输入1:
3
0 6 9
6 0 4
9 4 0
7 7 7
输入2:
3
0 17 20
17 0 10
20 10 0
15 9 12
输入3:
5
0 3 12 15 11
3 0 14 3 20
12 14 0 11 7
15 3 11 0 15
11 20 7 15 0
5 10 10 10 10
Sample Output
输出1:
17
输出2:
34
输出3:
28
Data Constraint
40%的数据满足N<=30且存在最多不超过4个间谍参加任务的最优方案;
50%的数据满足派遣每个间谍参加任务的费用是一样的。
Hint
样例1:将会在1和2,接着2和3间谍间举行会面,然后送间谍2参与任务。
样例2:将会在2和3间谍间举行会面,然后送间谍1和2参与任务。
样例3:将会在2和4,接着1和2,接着3和5间谍间举行会面,然后送间谍1和3(或1和5)参与任务。
超时空旅行
Special Judge
Test 0 1000 ms 32768 KB
Test 1 1000 ms 32768 KB
Test 2 1000 ms 32768 KB
Test 3 1000 ms 32768 KB
Test 4 1000 ms 32768 KB
Test 5 5000 ms 32768 KB
Test 6 1000 ms 32768 KB
Test 7 1000 ms 32768 KB
Test 8 1000 ms 32768 KB
Test 9 5000 ms 32768 KB
Description
在遥远的未来,行星之间的食品运输将依靠单向的贸易路线。每条路径直接连接两个行星,且其运输时间是已知的。
贸易商协会打算利用一项最近发现的新技术——超空间旅行,以增加一些新的航线。通过超空间旅行的航线也是单向的。由于该项技术仍处于试验阶段,超空间旅行的时间目前是未知的,但它不取决于行星之间的距离,所以每个超空间旅行的路线将花费等量的时间。
下图是三个相互联通的行星及其运输时间的例子。行星使用正整数标号,超空间旅行时间记为“x”(图片对应第二个输入样例):
运输时间以天计,并且始终是一个正整数。
贸易商协会希望对引进新航线的结果进行分析:对于某两个行星A和B,他们想知道对于任意的x,从A到B的最短路径的总运输时间的所有可能的值。例如,在上述情况中,从星球2到星球1的最短路径所需时间可以取值5(如果x≥5),4,3,2,或1天(如果x<5)
Input
输入的第一行包含两个整数P和R,分别代表行星的数目和航线数量,1≤P≤500,0≤R≤10000。
接下来的R条航线路径包含两或三个整数:行星标号C和D(1≤C,D≤P,C≠D),和T,从C到D的旅行时间。对于传统的路径,T是一个整数(1≤T≤1000000),超空间航线中,T是字符“x”。 可以存在多行有两个相同的行星。
下一行输入整数Q(1≤Q≤10),表示查询的数量。
以下Q行包含两个整数星球标号(A和B,A≠B),为贸易商协会的查询:“从A到B的最短路径时间的可能值是什么?
Output
输出必须包含Q行。
每一行都必须包含两个整数:不同的可能值的数目和它们的总和。如果不同的可能值的数目是无限的,该行只输出“inf”。如果不存在从A到B的路径,不同的可能值的数目及它们的总和都是0。
Sample Input
输入1:
4 4
1 2 x
2 3 x
3 4 x
1 4 8
3
2 1
1 3
1 4
输入2:
3 5
3 2 x
2 1 x
2 1 5
1 3 10
3 1 20
6
1 2
2 3
3 1
2 1
3 2
1 3
Sample Output
输出1:
0 0
inf
3 17
输出2:
inf
5 65
15 185
5 15
inf
1 10
Data Constraint
50%的数据满足P≤30,R≤300,T≤50P≤30, R≤300, T≤50P≤30,R≤300,T≤50。
如果一个询问的结果不是“inf”,则你的输出必须输出两个数,否则不得分;如果所有询问的第一问正确可以得一半分。
Hint
样例 1解释:
- 从2到1不存在可能的路径。
- 对于任意正整数x,从1到3的最短路径花费的时间是2x,所以答案是“inf”。
- 从1到4的最短路径可以花费3(当x=1),6(当x=2),或8(当x≥3)的时间,3+6+8=17
B组题目
照片
Time Limits: 1000 ms
Memory Limits: 131072 KB
Description
Farmer John决定为他的N头排列好的奶牛(1 <= N<= 200,000)做一张全景合照。这N头奶牛分别以1…N进行编号。他一共拍了M(1<= M <=100,000)张相片,每张相片都只包含有一部分位置连续的奶牛:第i张照片涵盖着编号从a_i到b_i的所有奶牛。当然,这些照片合起来并不保证包含所有的牛。
Farmer John拍摄完所有的相片后,注意到一个很有趣的现象:他拍的每张照片中有且仅有一只奶牛身上有斑点。 FJ知道他的奶牛中有一部分是身上有斑点的,但他从来没有数过这种奶牛的数目。请根据FJ的这些照片,确定可能出现的斑点牛的最大的数目;若从FJ的照片中无法推测斑点牛的数目,则输出-1。
Input
第1行:包含两个整数N、M。
第2… M+1… i +1行:每行包含两个整数a_i和b_i。
Output
输出仅一行,要求输出FJ根据他的照片所能推测出的斑点牛的最大数目;若无法推测这些奶牛的数目,则输出-1。
Sample Input
5 3
1 4
2 5
3 4
Sample Output
1
Data Constraint
1≤N≤200,0001\leq N\leq 200,0001≤N≤200,000
阴阳
Time Limits: 1000 ms
Memory Limits: 131072 KB
Description
Farmer John 正在在计划自己的农场漫步。他的农场的结构就像一棵树:农场有N个谷仓(1<= N <=100,000),分别由N-1条路链接。这样,他便可以通过这些谷仓间的道路遍及各个谷仓。Farmer John想要选择一条路线:这条路线的起点和终点分别为农场中两个不同的谷仓,这条路线不能重复经过一条边两次。Farmer John担心这条路径可能会偏长,所以他想在路线上寻找一个休息点(当然这个休息点不能为起点或者终点)。
每条边的两旁都是牛群,要么是Charcolais(白毛),要么是Angus(黑毛)。Farmer John是一个聪明人,所以他想要在他通过小路的同时平衡小路两侧阴阳的力量。他要选择一条路径使得他从起点到休息站,和从休息站到终点这两段路上都满足路两边的Charcolais牛群和Angus牛群总数量相同。
Farmer John好奇他能找到多少条如上所述的平衡的路径。我们认为,当且仅当两条路线的边的集合不同时,这两条路径才被认为是不同的,否则认为是相同的路线。就算路线上有多个有效的“休息站”的位置能使路线平衡,我们也只记为一条路线。
请帮助计算有多少条不同的平衡路线。
Input
第1行:包含一个整数N。
第2… N行:每行包含三个整数a_i、b_i和t_i,表示第i条路径连接的两个谷仓a_i、b_i。t_i表示第i条路边上的牛群种类:0表示Charcolais,1表示Angus。
Output
输出仅一行,包含一个整数,表示可能存在的路径数目。
Sample Input
7
1 2 0
3 1 1
2 4 0
5 2 0
6 3 1
5 7 1
Sample Output
1
Data Constraint
1≤N≤100,0001\leq N\leq 100,0001≤N≤100,000
Hint
不存在长度为2的路线,所以我们只能考虑长度为4的路线,路线3-1-2-5-7休息点设在2是一条平衡路线。
数字八
Time Limits: 1000 ms
Memory Limits: 131072 KB
Description
Farmer John的奶牛最近收到一块大理石。但不幸的是,这块石头有些不完整。为了说明这块石头的状况,我们就可以用一个N* N正方形网格(5 <= N <=300)来描述,其中字符’*‘代表石头的缺损部分,’.'表示石头完美无瑕的部分。
奶牛要在这一块大理石上雕刻数字“8”。然而,牛也需要FJ的帮助,以确定在这块大理石上最佳的雕刻位置。这里有几个要求来定义一个有效的数字8:
*数字8由上下两个矩形构成。
*数字8的上下两个矩形都满足至少有一个单元格在矩形内部,也就是说两个矩形都至少是3 *3的。
*数字8顶部的矩形的底边必须为底部矩形顶边的子集。
*数字8只能刻在大理石完美无瑕的部分。
*规定数字8的得分为上矩形和下矩形的面积的乘积。
请确定奶牛所能构造的最大数字8.
Input
第1行:包含一个整数N,表示大理石的边长。
第2… N+1行:第行描述的是大理石的第i-1行的状态,包含N个字符。其中字符’*‘代表石头的缺损部分,’.'表示石头完美无瑕的部分
Output
输出仅一行,包含一个整数,表示所能得到的最大的数字8得分。
Sample Input
15
...............
...............
...*******.....
.*....*.......*
.*......*....*.
....*..........
...*...****....
...............
..**.*..*..*...
...*...**.*....
*..*...*.......
...............
.....*..*......
.........*.....
...............
Sample Output
3888
Data Constraint
5<=N<=3005 <= N <=3005<=N<=300
Hint
上面的矩形面积为69=54,下面的矩形面积为126,得分为54*72=3888
总结
A组
今天的比赛是放反了吧!
往年的比赛(它们在同一个模拟赛):
于是今天A组的大众分200,B组的大众分50。
A组T1很显然是权值线段树,维护一下每一段数字中最前的位置和最后的位置,然后每次判断一下询问区间中数字排列的前后跨度是否等于数字差即可。
T2也很显然,是最小生成树,可以新建一个节点S,把S和每一个间谍 i 连一条值为MiM_iMi的边,间谍 i 和间谍 j 中间连一条费用为 i,j 会面花费的边。这是很容易想的。
T3比赛时想错了,维护了走x和不走x的2个最短路,结果还打错了。。。
其实T3要维护所有数量的x的情况,然后就得到了很多条路线,其中第 i 条可以视作kx+bkx+bkx+b,其中k是x边的数量,b是非x边之和。
这是不是很眼熟呢?把设x的值为x轴,长度为y轴,那么我们就可以画出一堆直线,显然最优答案会组成一个上凸壳,用类似于斜率优化的方法搞就可以了。
那么水的题目,我竟然没有AK,太不应该了。
B组
从某个同学的总结就可以看出今天的B组有多么∗∗**∗∗。
T1设fif_ifi表示在 i 放一只斑点奶牛时,斑点奶牛的最多数量,lil_ili表示在 i 放了以后前面最远在哪里必须放上一只奶牛,rir_iri表示在 i 放了以后前面最近在哪里可以放上一只奶牛。
一通乱搞即可。
T2点分治,不会。
T3
可以先处理上半个矩形,在处理下半个矩形。
考虑下面这个图形
其中蓝色部分是当前处理到的上部分,可以设fi,j,kf_{i,j,k}fi,j,k表示当前处理到的矩形左边界为 i ,右边界为 j ,下边界为k,则
fi,j,k=max{−1,第(k,i)或(k,j)个格子破损fi,j,k−1+1,fi,j,k−1≠−10从(k,i)到(k,j)无破损f_{i,j,k}=\max\begin{cases}
-1,&\text{第(k,i)或(k,j)个格子破损}\\
f_{i,j,k-1}+1,&f_{i,j,k-1}\neq-1\\
0&\text{从(k,i)到(k,j)无破损}
\end{cases}fi,j,k=max⎩⎨⎧−1,fi,j,k−1+1,0第(k,i)或(k,j)个格子破损fi,j,k−1=−1从(k,i)到(k,j)无破损
用si,j,ks_{i,j,k}si,j,k表示此时的面积,则si,j,k=(j−i−1)×(fi,j,k−2)s_{i,j,k}=(j-i-1)\times(f_{i,j,k}-2)si,j,k=(j−i−1)×(fi,j,k−2)
然后判断一下如果一个大矩形包含一个小矩形,那么用小矩形的面积更新大矩形的面积。
接着倒过来做,合并一下上下矩形就好了。
CODE
A组
T1
#include<cstdio>
using namespace std;
#define N 200005
#define M 1000005
#define lson k<<1
#define rson k<<1|1
char ch;
inline char gc()
{
static char buf[M],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,N,stdin),p1==p2)?EOF:*p1++;
}
inline void read(int &x)
{
while(ch=gc(),ch<'0'||ch>'9');x=ch-'0';
while(ch=gc(),ch>='0'&&ch<='9') x=x*10+ch-'0';
}
int max[N*18],min[N*18],a[N],maxx,minn;
inline int mymax(int x,int y){return x>y?x:y;}
inline int mymin(int x,int y){return x<y?x:y;}
inline void update(int k)
{
if(max[lson]>max[rson]) max[k]=max[lson];
else max[k]=max[rson];
if(min[lson]<min[rson]) min[k]=min[lson];
else min[k]=min[rson];
}
void change(int k,int l,int r,int id,int num)
{
if(l==r)
{
max[k]=min[k]=num;
return;
}
int mid=l+r>>1;
if(id<=mid) change(lson,l,mid,id,num);
else change(rson,mid+1,r,id,num);
update(k);
}
void qry(int k,int l,int r,int x,int y)
{
if(l==x&&r==y)
maxx=mymax(maxx,max[k]),
minn=mymin(minn,min[k]);
else
{
int mid=l+r>>1;
if(y<=mid) qry(lson,l,mid,x,y);
else if(x>mid) qry(rson,mid+1,r,x,y);
else qry(lson,l,mid,x,mid),qry(rson,mid+1,r,mid+1,y);
}
}
/*void print(int k,int l,int r)
{
printf("%d\t%d\t%d\t%d\t%d\n",k,l,r,min[k],max[k]);
if(l==r) return;
int mid=l+r>>1;
print(lson,l,mid);
print(rson,mid+1,r);
}*/
int main()
{
int n,m,i,x,y;
read(n),read(m);
for(i=1;i<=n;i++)
read(a[i]),change(1,1,n,a[i],i);
//print(1,1,n);
while(m--)
{
read(i),read(x),read(y);
if(i==1)
change(1,1,n,a[x],y),
change(1,1,n,a[y],x),
a[x]^=a[y],a[y]^=a[x],a[x]^=a[y];
else
maxx=0,minn=N,
qry(1,1,n,x,y),
puts(maxx-minn==y-x?"YES":"NO");
}
return 0;
}
T2
//I saw a spy,fly in the sky,eat a pie,with a knife,and a kite.I asked him why,he said he'll die,because of the flies,so he fly,with a kite.
#include<cstdio>
#include<algorithm>
using namespace std;
#define N 1005
#define M 501005
struct edge
{
int start,end,lenth;
}a[M];
int f[N],m,ans;char ch;
inline char gc()
{
static char buf[M],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,N,stdin),p1==p2)?EOF:*p1++;
}
inline void read(int &x)
{
while(ch=gc(),ch<'0'||ch>'9');x=ch-'0';
while(ch=gc(),ch>='0'&&ch<='9') x=x*10+ch-'0';
}
bool cmp(edge x,edge y){return x.lenth<y.lenth;}
inline int getfather(int k)
{
if(f[k]==k) return k;
return f[k]=getfather(f[k]);
}
inline void build()
{
sort(a+1,a+m+1,cmp);
int i,x,y;
for(i=1;i<=m;i++)
{
x=a[i].start,y=a[i].end;
if(getfather(x)!=getfather(y))
{
f[f[x]]=f[y];
ans+=a[i].lenth;
}
}
}
int main()
{
int n,i,j,k;
read(n),n++;
for(i=1;i<n;i++)
for(j=1;j<n;j++)
{
read(k);
if(i<j) a[++m]=(edge){i,j,k};
}
for(i=1;i<n;i++) read(k),a[++m]=(edge){n,i,k},f[i]=i;
f[n]=n,build();
printf("%d\n",ans);
return 0;
}
T3
#include<cstdio>
#include<queue>
using namespace std;
#define ll long long
#define inf 999999999
#define M 10005
#define N 505
struct edge{int end,lenth,next;}a[M<<1];
struct node{int x,y;}temp;
struct line{ll k,b;}num[M],stack[M];
queue<node>data;
int fir[N],dis[N][N],n,m,i,j,s;
bool exist[N][M];char ch;
inline char gc()
{
static char buf[1000005],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,N,stdin),p1==p2)?EOF:*p1++;
}
inline void read(int &x)
{
while(ch=gc(),ch!='x'&&(ch<'0'||ch>'9'));
if(ch=='x'){x=0;return;}
x=ch-'0';
while(ch=gc(),ch>='0'&&ch<='9') x=x*10+ch-'0';
}
inline void inc(int x,int y,int z)
{a[++s]=(edge){y,z,fir[x]},fir[x]=s;}
inline void spfa(int st)
{
int x,y,u;
for(i=1;i<=n;i++)
for(j=0;j<=n;j++)
dis[i][j]=inf,exist[i][j]=1;
data.push((node){st,0}),dis[st][0]=0;
while(!data.empty())
{
temp=data.front(),data.pop();
x=temp.x,y=temp.y,exist[x][y]=1;
for(i=fir[x];i;i=a[i].next)
{
u=a[i].end;
if(a[i].lenth)
{
if(dis[u][y]>dis[x][y]+a[i].lenth)
{
dis[u][y]=dis[x][y]+a[i].lenth;
if(exist[u][y]) exist[u][y]=0,data.push((node){u,y});
}
}
else if(dis[u][y+1]>dis[x][y])
{
dis[u][y+1]=dis[x][y];
if(exist[u][y+1]) exist[u][y+1]=0,data.push((node){u,y+1});
}
}
}
}
inline double crossing(line u,line v)
{return (v.b-u.b+0.0)/(double)(u.k-v.k);}
inline ll count(ll x,ll y)
{return (x+y)*(y-x+1)>>1;}
int main()
{
int q,i,j,x,y,z,last,now,top;
ll sum;bool no;
read(n),read(m);
for(i=1;i<=m;i++)
{
read(x),read(y),read(z);
inc(x,y,z);
}
read(q);
while(q--)
{
read(x),read(y),spfa(x);
if(dis[y][0]==inf)
{
for(i=1,no=1;i<=n;i++)
if(dis[y][i]<inf){no=0;break;}
if(no) puts("0 0");else puts("inf");
continue;
}
for(i=n,top=0;i>=0;i--)
{
num[i]=(line){i,dis[y][i]};
if(i&&dis[y][i]>=dis[y][i-1]) continue;
while(top>1&&crossing(stack[top-1],stack[top])>crossing(stack[top],num[i])) top--;
while(top&&stack[top].b>dis[y][i]) top--;
stack[++top]=num[i];
}
if(top==1){printf("1 %lld\n",stack[1].b);continue;}
for(i=1,last=1,sum=0;i<top;last=now+1,i++)
{
now=crossing(stack[i],stack[i+1]);
if(last<=now)
sum+=1LL*count(last,now)*stack[i].k+1LL*(now-last+1)*stack[i].b;
}
if(crossing(stack[top-1],stack[top])>now) now++,sum+=stack[top].b;
printf("%d %lld\n",now,sum);
}
return 0;
}
B组
T1
#include<cstdio>
using namespace std;
#define N 200005
int f[N],l[N],r[N],queue[N];
inline int min(int x,int y){return x<y?x:y;}
inline int max(int x,int y){return x>y?x:y;}
int main()
{
int n,m,i,j,a,b,head=1,tail=1;
scanf("%d%d",&n,&m);
for(i=1;i<=n+1;i++) r[i]=i-1;
for(i=1;i<=m;i++)
scanf("%d%d",&a,&b),
l[b+1]=max(l[b+1],a),
r[b]=min(r[b],a-1);
for(i=2;i<=n+1;i++) l[i]=max(l[i-1],l[i]);
for(i=n;i>0;i--) r[i]=min(r[i+1],r[i]);
for(i=j=1;i<=n+1;i++)
{
for(;j<=r[i];j++)
{
if(f[j]>-1)
{
while(head<=tail&&f[queue[tail]]<f[j]) tail--;
queue[++tail]=j;
}
}
while(head<=tail&&queue[head]<l[i]) head++;
if(head>tail) f[i]=-1;
else if(i<=n) f[i]=f[queue[head]]+1;
else f[i]=f[queue[head]];
}
printf("%d\n",f[n+1]);
return 0;
}
T3
#include<cstdio>
#include<cstring>
using namespace std;
#define N 305
inline char gc()
{
static char buf[200005],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,N,stdin),p1==p2)?EOF:*p1++;
}
short f[2][N][N],sum[N][N];
int s[N][N][N];
bool a[N][N];char ch;
inline void readint(int &x)
{
while(ch=gc(),ch<'0'||ch>'9');x=ch-'0';
while(ch=gc(),ch>='0'&&ch<='9') x=x*10+ch-'0';
}
inline void readchar(){while(ch=gc(),ch!='.'&&ch!='*');}
inline int max(int x,int y){return x>y?x:y;}
inline bool judge(int k,int i,int j){return sum[k][j]-sum[k][i-1]==0;}//(k,i) to (k,j)
int main()
{
int n,i,j,k,t,now,las,ans=0;
readint(n);
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
readchar(),a[i][j]=(ch=='*'),
sum[i][j]=sum[i][j-1]+a[i][j];
memset(f[0],-1,sizeof(f[0]));
for(k=now=1,las=0;k<=n;k++,now^=1,las^=1)
{
memset(f[now],-1,sizeof(f[now]));
for(i=1;i<n;i++)
{
for(j=i+1;j<=n;j++)
{
if(a[k][i]||a[k][j]) continue;
if(f[las][i][j]>-1) f[now][i][j]=f[las][i][j]+1;
else if(judge(k,i,j)) f[now][i][j]=0;
if(f[now][i][j]>2&&j>i+1)
{
s[k][i][j]=(j-i-1)*(f[now][i][j]-1);
}
}
}
}
for(k=1;k<=n;k++)
for(i=3;i<n;i++)
for(j=1;j<=n-i;j++)
s[k][j][j+i]=max(s[k][j][j+i],max(s[k][j+1][j+i],s[k][j][j+i-1]));
memset(f[las],-1,sizeof(f[las]));
for(k=n;k>0;k--,now^=1,las^=1)
{
memset(f[now],-1,sizeof(f[now]));
for(i=1;i<n;i++)
{
for(j=i+1;j<=n;j++)
{
if(a[k][i]||a[k][j]) continue;
if(f[las][i][j]>-1) f[now][i][j]=f[las][i][j]+1;
else if(judge(k,i,j)) f[now][i][j]=0;
if(f[now][i][j]>2&&j>i+1&&judge(k,i,j))
{
ans=max(ans,(j-i-1)*(f[now][i][j]-1)*s[k][i][j]);
}
}
}
}
if(!ans) ans=-1;
printf("%d\n",ans);
return 0;
}