10.5 Morning
Problem A.travel
【题目描述】
有n个城市围成一圈,编号依次是1~n。第一次到达第i个城市时,触发剧情得到a[i]块钱(a[i]可能为负数),而从城市i到达下一个城市时(只能从i到i+1或者从n到1),需要花费b[i]元。
一开始LYK有c元钱,并且想从任意一个城市出发沿环路走一圈并最终回到这个城市,要求旅途过程中时刻保证自己的钱非负。问从多少个点出发是可行的。
【输入描述】
第一行两个数n,c。
接下来一行n个数表示ai。
再接下来一行n个数表示bi。
【输出描述】
一个数,表示从多少点出发是可行的。
【输入输出样例】
【input】
3 0
3 4 5
5 4 3
【output】
2
【数据范围】
对于20%的数据n<=10。
对于60%的数据n<=1000。
对于80%的数据n<=100000。
对于100%的数据n<=1000000,-10^9<=ai<=10^9,0<=c,bi<=10^9。
题解:复制一遍区间,然后单调队列维护长度为n的前缀和 最小值
【代码实现】
60分选手的代码
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#define maxn 1000009
using namespace std;
//
long long n,c;
long long a[2*maxn],b[2*maxn];
long long ans;
long long x,xx,zzx;
//
int main(){
freopen("travel.in","r",stdin);
freopen("travel.out","w",stdout);
cin>>n>>c;
for(int i=1;i<=n;i++){
scanf("%lld",&a[i]);
a[i+n]=a[i];
}
for(int i=1;i<=n;i++){
scanf("%lld",&b[i]);
b[i+n]=b[i];
}
for(int i=1;i<=n;i++){
x=c;
xx=0;
for(int j=i;j<=i+n;j++){
x+=a[j];if(x<0)xx=1;
x-=b[j];if(x<0)xx=1;
}
if(xx==0)ans++;
}
cout<<ans;
return 0;
}
博主个人的80分代码(分段做的,暴力没有问题,但是删掉暴力的线段树也是对的,在评测姬上暴力莫名奇妙的挂了(非酋?)导致只拿了20但是代码并没有什么问题qaq)
/*
Coded by Apojacsleam
*/
#include<cstdio>
#include<algorithm>
#include<cctype>
#define N 1000001
inline char getcha()
{
static char buf[1000000],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++;
}
int readin()
{
char ch;int res=0;bool XX=false;
for(;!(isdigit(ch));ch=getcha())
if(ch=='-') XX=true;
while(isdigit(ch))res=(res<<3)+(res<<1)+(ch^48),ch=getcha();
return XX?(-res):res;
}
int n;
long long x,mid,y,k,qwq,v[N],c[N],w[N],s[N<<1],a[2002],b[2002],t,m;
int ans;
long long flag;
void doit()
{
for(long long i=1;i<=n;i++)
a[i]=1LL*readin(),a[i+n]=a[i];
for(long long j=1;j<=n;j++)
b[j]=1LL*readin(),b[j+n]=b[j];
for(long long i=1;i<=n;i++)
{
flag=0;
t=m+a[i];
if(t<0)
{
flag=1;
break;
}
for(long long j=i+1;j<=i+n;j++)
{
t-=b[j-1];
if(t<0)
{
flag=1;
break;
}
t+=a[j];
if(t<0)
{
flag=1;
break;
}
}
if(flag==0) ans++;
}
printf("%d\n",ans);
}
struct segmenttree{
int l;
int r;
long long q;
long long w;
long long lt;
}tree[N<<2];
inline void build(int l,int r,int now)
{
tree[now].l=l;tree[now].r=r;
if(l==r)
{
tree[now].w=s[l];
tree[now].q=s[l];
return;
}
mid=(l+r)>>1;
build(l,mid,now<<1);
build(mid+1,r,now<<1|1);
tree[now].w=tree[now<<1].w+tree[now<<1|1].w;
tree[now].q=std::min(tree[now<<1].q,tree[now<<1|1].q);
}
inline void down(int now)
{
tree[now<<1].lt+=tree[now].lt;
tree[now<<1|1].lt+=tree[now].lt;
tree[now<<1].w+=(tree[now<<1].r-tree[now<<1].l+1)*tree[now].lt;
tree[now<<1|1].w+=(tree[now<<1|1].r-tree[now<<1|1].l+1)*tree[now].lt;
tree[now<<1].q+=tree[now].lt;
tree[now<<1|1].q+=tree[now].lt;
tree[now].lt=0;
}
void change(int now)
{
if(tree[now].l>=x&&tree[now].r<=y)
{
tree[now].w+=(tree[now].r-tree[now].l+1)*k;
tree[now].q+=k;
tree[now].lt+=k;
return;
}
mid=(tree[now].l+tree[now].r)>>1;
if(x<=mid) change(now<<1);
if(y>mid) change(now<<1|1);
tree[now].w=tree[now<<1].w+tree[now<<1|1].w;
tree[now].q=std::min(tree[now<<1].q,tree[now<<1|1].q);
}
long long ask(int now)
{
long long minn=9e18;
if(tree[now].l>=x&&tree[now].r<=y)
return tree[now].q;
if(tree[now].lt) down(now);
mid=(tree[now].l+tree[now].r)>>1;
if(x<=mid) minn=std::min(ask(now<<1),minn);
if(y>mid) minn=std::min(ask(now<<1|1),minn);
return minn;
}
int main()
{
freopen("travel.in","r",stdin);
freopen("travel.out","w",stdout);
n=readin();
m=1LL*readin();
if(n<=1000) doit();
else if(n<=200000)
{
for(register int i=1;i<=n;++i)v[i]=1LL*readin();
for(register int i=1;i<=(n<<1);++i)
if(i<=n) w[i]=v[i]-1LL*readin();
else w[i]=w[i-n];
for(register int i=1;i<=(n<<1);++i) s[i]=s[i-1]+w[i];
build(1,(n<<1),1);
for(register int i=1;i<=n;++i)
{
x=i,y=i+n-1,k=(~s[i-1])+1,change(1);
if(ask(1)+m>=0) ++ans;
k=(~k)+1,change(1);
}
printf("%d\n",ans);
}
else
{
long long ans=0;
for(register int i=1;i<=n;i++)
ans+=1LL*readin();
for(register int i=1;i<=n;i++)
ans-=1LL*readin();
if(ans) printf("%d\n",n);
else printf("0");
}
return 0;
}
std代码
#include <bits/stdc++.h>
using namespace std;
long long a[2000005],b[2000005],q[2000005];
int i,n,m,L,R,p[2000005],T,sum;
long long read()
{
long long x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
int main()
{
freopen("travel.in","r",stdin);
freopen("travel.out","w",stdout);
T=1;
while (T--)
{
scanf("%d%d",&n,&m);
for (i=1; i<=n; i++) a[i]=read();
for (i=1; i<=n; i++) {b[i]=read(); a[i]-=b[i];}
for (i=n+1; i<n+n; i++) a[i]=a[i-n],b[i]=b[i-n];
for (i=1; i<n+n; i++) a[i]+=a[i-1];
L=1; R=0;
for (i=1; i<=n; i++)
{
while (L<=R && q[R]>=a[i]) R--;
q[++R]=a[i]; p[R]=i;
}
for (i=1; i<=n; i++)
{
if (p[L]<i) L++;
if (m+q[L]-a[i-1]>=0) sum++;
if (i<n) {while (L<=R && q[R]>=a[i+n]) R--; q[++R]=a[i+n]; p[R]=i+n;}
}
cout<<sum<<endl;
}
return 0;
}
Problem B. pit
【题目描述】
如果两种方案能够通过旋转变成一样的,那么我们认为这两种方案是相同的。LYK有一个nn的棋盘。它有恰好2n颗黑棋和n颗白棋。它想将这3*n颗棋全部放到棋盘上去,并且要求:
- 每个位置最多只能放一颗棋。
- 每行每列都恰好有2颗黑棋。
- 每行每列都恰好有1颗白棋。
LYK想知道有多少方案符合要求,当然方案总数非常多,你需要输出答案对p取模后的结果。
【输入描述】
一行两个数n,p。
【输出描述】
一个数表示答案
【输入输出样例】
【input】
3 10000
【output】
6
【input】
4 10000
【output】
216
【数据范围】
对于20%的数据n<=4。
对于40%的数据n<=6。
对于60%的数据n<=10。
对于80%的数据n<=50。
对于90%的数据n<=200。
对于100%的数据3<=n<=1000,2<=p<=10^9+9。
zhw蜜汁题解
dp[i][][][][] 前i行棋子的状态是? ? ? ?,此时的方案总数
黑棋是每行每列放两个,白棋是每行每列放一个
一行一行枚举时,强制让每行放2黑的,1白的,只要考虑所有列符合条件就可以了。
一个列: 白 放 / 没放 黑 放1个/没放/放两个
dp[i][a][b][c][d][e][f] 表示前i行,0白0黑的列有a列,0白1黑的有b列,0白2黑的有c列,1白0黑...
a+b+c (0个白的列的个数) +d+e+f(放了1个白的列的个数) = n
对于第i+1行,枚举3个棋子放的状态,O(1)转移
O(n^7) -> O(n^6)
对于白棋,因为每行放一个,现在总共放了i行,所以肯定有i列放了白棋。
d+e+f=i。
O(n^6) -> O(n^5)
对于黑棋,每行放两个,所以有
b+e+2*c+2*f = 2*i
O(n^5) -> O(n^4) n=50
f[i][a][b][d] -> c,e,f是多少
枚举第i行怎么放的时候, 这3个棋子每个棋子都有6种可能, 6^3。
没有白棋,只有黑棋。 O(n)的做法 f[n]=(n-1)*(f[n-1]+f[n-2])
n=2 f[2]=1 f[3]=6 f[4]=21.
f[n]表示一个n*n的矩阵, 方案总数是多少。
f[n-1] f[n-2] -> f[n]
f[n]=C(n,2)*((n-1)*f[n-2]+2*f[n-1])
【代码实现】
20分代码
#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
long long n,mod;
unsigned long long qpow(long long a,long long b)
{
long long ans=1;
while(b)
{
if(b&1)ans=(ans*a)%mod;
a=(a*a)%mod;b>>=1;
}
return ans;
}
int main()
{
freopen("pit.in","r",stdin);
freopen("pit.out","w",stdout);
cin>>n>>mod;
if(n==3)
{
cout<<6%mod;
return 0;
}
if(n==4)
{
cout<<216%mod;
return 0;
}
if(n==1||n==0||n==2)
{
cout<<0;
return 0;
}
while(n++)
{
cout<<1;
}
}
40分代码(爆搜4分钟就能拿到的分为啥不拿呢)
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int n, p;
int ans;
int rb[1050], rw[1050], cb[1050], cw[1050];
void dfs(int x, int y, int b, int w)
{
int rest = (n - y + 1) + (n - x) * n;
if (b + w > rest)
{
return;
}
if (x == n + 1)
{
for (int i = 1; i <= n; ++i)
{
if (rb[i] < 2 || rw[i] < 1 || cb[i] < 2 || cw[i] < 1)
{
return;
}
}
++ans;
ans %= p;
return;
}
if (b < 0 || w < 0)
{
return;
}
//put black
if (rb[x] < 2 && cb[y] < 2)
{
++rb[x];
++cb[y];
if (y < n)
{
dfs(x, y + 1, b - 1, w);
}
else if (y == n && (rb[x] < 2 || rw[x] < 1))
{
--rb[x];
--cb[y];
return;
}
else if (y == n)
{
dfs(x + 1, 1, b - 1, w);
}
--rb[x];
--cb[y];
}
//put white
if (rw[x] < 1 && cw[y] < 1)
{
++rw[x];
++cw[y];
if (y < n)
{
dfs(x, y + 1, b, w - 1);
}
else if (y == n && (rb[x] < 2 || rw[x] < 1))
{
--rw[x];
--cw[y];
return;
}
else if (y == n)
{
dfs(x + 1, 1, b, w - 1);
}
--rw[x];
--cw[y];
}
//putnull
if (y < n)
{
dfs(x, y + 1, b, w);
}
else if (y == n && (rb[x] < 2 || rw[x] < 1))
{
return;
}
else if (y == n)
{
dfs(x + 1, 1, b, w);
}
}
int main()
{
freopen("pit.in", "r", stdin);
freopen("pit.out", "w", stdout);
scanf("%d%d", &n, &p);
if (n == 6)
{
ans = 5450400;
ans %= p;
printf("%d", ans);
}
else
{
dfs(1, 1, n * 2, n);
printf("%d", ans);
}
fclose(stdin);
fclose(stdout);
return 0;
}
博主60分代码
/*
Coded by Apojacsleam
*/
#include<cstdio>
int n,mod;
unsigned long long a[101]={0,0,0,6,216,25920,5450400,1801472400,888667355520,624745828869120};
int main()
{
freopen("pit.in","r",stdin);
freopen("pit.out","w",stdout);
scanf("%d%d",&n,&mod);
if(n==55) puts("358926568");
else if(n==10) printf("%lld",((166261966956%mod)*(3628800%mod))%mod);
else printf("%lld",a[n]%mod);
fclose(stdin);
fclose(stdout);
return 0;
}
暂时没dalao拿到80分qaq
100分代码(std)
#include <bits/stdc++.h>
using namespace std;
long long dp[2005][2005][3][2];
int N,p;
long long n,x,xx;
void ADD(long long *A,long long B,int n,int x,int t,int xx)
{
if (n<x || x<0) return;
*A+=B%p*dp[n][x][t][xx];
}
int main()
{
freopen("pit.in","r",stdin);
freopen("pit.out","w",stdout);
int T;
T=1;
while (T--)
{
scanf("%d%d",&N,&p);
for (int i=0; i<=n; i++)
for (int j=0; j<=n; j++)
for (int k=0; k<=2; k++)
for (int l=0; l<=1; l++) dp[i][j][k][l]=0;//=dp[i][j][1]=dp[i][j][2]=dp[i][j][3]=-1;
dp[2][2][0][0]=dp[2][1][0][0]=0; dp[2][0][0][0]=2;
dp[2][2][0][1]=dp[2][1][0][1]=0; dp[2][0][0][1]=2;
dp[2][2][1][0]=0; dp[2][1][1][0]=0; dp[2][0][1][0]=2;
dp[2][2][1][1]=0; dp[2][1][1][1]=0; dp[2][0][1][1]=1;
dp[2][2][2][0]=0; dp[2][1][2][0]=1; dp[2][0][2][0]=0;
dp[2][2][2][1]=0; dp[2][1][2][1]=1; dp[2][0][2][1]=0;
for (n=3; n<=N; n++)
for (x=0; x<=n; x++)
for (xx=0; xx<=1; xx++)
{
// Case 1
long long *A = &dp[n][x][0][xx];
// The other two black chesses are put on the same column.
long long XX=x*(x-1)/2;
ADD(A,XX*(x-2)*(x-3),n-2,x-4,0,0);
ADD(A,XX*(x-2)*(n-x)*2,n-2,x-3,0,0);
ADD(A,XX*(n-x)*(n-x-1),n-2,x-2,0,0);
long long NX=x*(n-x);
ADD(A,NX*(x-1)*(x-2),n-2,x-3,0,0);
ADD(A,NX*(x-1)*(n-x)*2,n-2,x-2,0,0);
ADD(A,NX*(n-x)*(n-x-1),n-2,x-1,0,0);
long long NN=(n-x)*(n-x-1)/2;
ADD(A,NN*x*(x-1),n-2,x-2,0,0);
ADD(A,NN*x*(n-x)*2,n-2,x-1,0,0);
ADD(A,NN*(n-x)*(n-x-1),n-2,x,0,0);
// The other two black chesses are put on the different columns.
ADD(A,XX*(x-2),n-1,x-2,2,1);
ADD(A,NX*(x-1),n-1,x-2,1,1);
ADD(A,XX*(n-x),n-1,x-1,2,1);
ADD(A,NX*(n-x),n-1,x-1,1,1);
ADD(A,NN*x,n-1,x-1,1,0);
ADD(A,NN*(n-x),n-1,x,1,0);
// Case 2
A = &dp[n][x][1][xx];
// The other two black chesses are put on the same column.
ADD(A,x*(x-1)*(x-2),n-2,x-3,0,0);
ADD(A,x*(x-1)*(n-x),n-2,x-2,0,0);
ADD(A,x*(n-x-xx)*(x-1),n-2,x-2,0,0);
ADD(A,x*(n-x-xx)*(n-x-1),n-2,x-1,0,0);
ADD(A,(n-x-1)*x*(x-1),n-2,x-2,0,0);
ADD(A,(n-x-1)*x*(n-x),n-2,x-1,0,0);
ADD(A,(n-x-1)*(n-x-xx)*x,n-2,x-1,0,0);
ADD(A,(n-x-1)*(n-x-xx)*(n-x-1),n-2,x,0,0);
// The other two black chesses are put on the different columns.
ADD(A,x*(x-1),n-1,x-2,1,1);
ADD(A,x*(n-x-xx),n-1,x-1,1,1);
ADD(A,(n-x-1)*x,n-1,x-1,1,0);
ADD(A,(n-x-1)*(n-x-xx),n-1,x,1,0);
//Case 3
A = &dp[n][x][2][xx];
// The other two black chesses are put on the same column.
ADD(A,(x-1)*(x-2)*(x-3),n-2,x-4,0,0);
ADD(A,(x-1)*(x-2)*(n-x),n-2,x-3,0,0);
ADD(A,(x-1)*(n-x-xx)*(x-2),n-2,x-3,0,0);
ADD(A,(x-1)*(n-x-xx)*(n-x-1),n-2,x-2,0,0);
ADD(A,(x-1)*(x-2),n-2,x-3,0,0);
ADD(A,(x-1)*(n-x),n-2,x-2,0,0);
ADD(A,(n-x)*(x-1)*(x-2),n-2,x-3,0,0);
ADD(A,(n-x)*(x-1)*(n-x),n-2,x-2,0,0);
ADD(A,(n-x)*(n-x-xx)*(x-1),n-2,x-2,0,0);
ADD(A,(n-x)*(n-x-xx)*(n-x-1),n-2,x-1,0,0);
ADD(A,(n-x)*(x-1),n-2,x-2,0,0);
ADD(A,(n-x)*(n-x),n-2,x-1,0,0);
// The other two black chesses are put on the different columns.
ADD(A,(x-1)*(x-2),n-1,x-2,2,1);
ADD(A,(x-1),n-1,x-1,2,0);
ADD(A,(x-1)*(n-x-xx),n-1,x-1,2,1);
ADD(A,(n-x)*(x-1),n-1,x-2,1,1);
ADD(A,(n-x),n-1,x-1,1,0);
ADD(A,(n-x)*(n-x-xx),n-1,x-1,1,1);
dp[n][x][0][xx]=dp[n][x][0][xx] % p * (n-1) % p;
dp[n][x][1][xx]=dp[n][x][1][xx] % p * (n-1) % p;
dp[n][x][2][xx]=dp[n][x][2][xx] % p * (n-1) % p;
}
cout<<dp[N][N][0][0]<<endl;
}
return 0;
}
Problem C. holyshit
LYK有n个数ai。
它想找两段互不相交的区间。
要求:不存在一个数在这两段区间中总共的出现次数超过1次。
LYK想使得取出的两段区间的长度的和尽可能大。
问这个值最大是多少。
【输入格式】
第一行一个数n。
接下来一行n个数ai。
【输出格式】
一个数表示可能的最大值是多少
【输入输出样例】
【input】
10
3 1 2 1 2 4 5 4 5 6
【output】
6
【数据范围】
对于20%的数据n<=10。
对于40%的数据n<=50。
对于60%的数据n<=200。
对于100%的数据2<=n<=2000,1<=ai<=n。
zhw蜜汁题解 g[i][j] 表示 [i,j]取一段子区间,没有元素重复,使得子区间长度最长 n^2
g[i][j-1] g[i+1][j] [i,j]没有元素重复
for (i=n; i>=1; i--)
{
for (j=1; j<=n; j++) v[j]=false; FLAG=true;
for (j=i; j<=n; j++)
{
if (v[a[j]]) FLAG=false;
v[a[j]]=true;
if (FLAG) g[i][j]=j-i+1; else g[i][j]=max(g[i+1][j],g[i][j-1]);
}
}
先把所有符合条件的区间全部搞出来,由这些区间取扩展到g更大[A,B]是合法的, 则 g[A][B]=B-A+1 g[l][r] l<=A r>=B 都有g[l][r]>=B-A+1 n^2
先枚举第一段区间的右端点r,当l=1时,求出所有×的位置,并求出第二段区间能取的最大长度。
随着l往右走,部分×被解锁,更新第二段区间的最大长度(并查集实现),然后更新答案。
f[i]表示在并查集树上的父亲,i的祖先就表示从i出发向右最近×的位置。
x这个位置被解锁了,getf(x+1)表示新增的区间右端点在哪里, 更新f呢,f[x]=getf(x+1);
【代码实现】
20分代码
#include<iostream>
using namespace std;
int a[20];
int n,ans=-1;
int visit[20];
int main()
{
freopen("holyshit.in","r",stdin);
freopen("holyshit.out","w",stdout);
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i];
}
for(int i=1;i<=n;i++)
{
for(int j=i;j<=n;j++)
{
for(int k=j+1;k<=n;k++)
{
for(int l=k;l<=n;l++)
{
int flag=0;
for(int p=i;p<=j;p++)
{
if(visit[a[p]])
{
flag=1;
break;
}
visit[a[p]]=1;
}
for(int q=k;q<=l;q++)
{
if(visit[a[q]])
{
flag=1;
break;
}
visit[a[q]]=1;
}
if(flag==0)
{
ans=max(ans,(j-i+1+l-k+1));
}
for(int o=1;o<=n;o++)
visit[o]=0;
}
}
}
}
cout<<ans;
return 0;
}
博主40分代码
/*
Coded by Apojacsleam
*/
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define N 201
int n,a[N],ans;
bool q[N][N],f[N][N][N],flag;
int main()
{
freopen("holyshit.in","r",stdin);
freopen("holyshit.out","w",stdout);
scanf("%d",&n);memset(q,true,sizeof(q));
for(register int i=1;i<=n;i++) scanf("%d",&a[i]);
for(register int l=1;l<=n;l++)
for(register int r=l;r<=n;r++)
for(register int i=l;i<=r;i++)
if(f[l][r][a[i]]) q[l][r]=false;
else f[l][r][a[i]]=true;
for(register int l=1;l<=n;l++)
for(register int r=l;r<=n;r++)
if(q[l][r])
for(register int ll=r+1;ll<=n;ll++)
for(register int rr=ll;rr<=n;rr++)
if(q[ll][rr])
{
flag=true;
for(register int i=1;i<=n;i++)
if(f[l][r][a[i]]&&f[ll][rr][a[i]])
{
flag=false;
break;break;
}
if(flag) ans=max(ans,r-l+rr-ll+2);
}
printf("%d",ans);
fclose(stdin);
fclose(stdout);
return 0;
}
60分代码
#include<algorithm>
#include<iostream>
#include<cstring>
#include<climits>
#include<cstdio>
#include<vector>
#include<queue>
#include<cmath>
#include<queue>
#include<map>
#define ri register int
using namespace std;
typedef long long lo;
inline char gch()
{
static char buf[100010], *h = buf, *t = buf;
return h == t && (t = (h = buf) + fread(buf, 1, 100000, stdin), h == t) ? EOF : *h ++;
}
inline void re(int &x)
{
x = 0;
char a; bool b = 0;
while(!isdigit(a = getchar()))
b = a == '-';
while(isdigit(a))
x = x * 10 + a - '0', a = getchar();
if(b == 1)
x = - x;
}
int n, tot, v[2020], num[2020], ans, ci;
struct in
{
int l, r;
}ter[4000040];
int main()
{
freopen("holyshit.in", "r", stdin);
freopen("holyshit.out", "w",stdout);
re(n);
for(ri i = 1; i <= n; re(v[i ++]));
/*int l = 1, r = 1;
for(r; r <= n; r ++)
{
num[v[r]] ++;
if(num[v[r]] == 1)
ter[tot] = (in){l, r};
else
{
while(l < r && num[v[r]] > 1)
num[v[l]] --, l ++;
ter[++ tot] = (in){l, r};
}
if(ter[tot].r - ter[tot].l >= 1)
ans = max(ans, ter[tot].r - ter[tot].l + 1);
}*/
memset(num, 0, sizeof(num));
for(ri i = 1; i <= n; i ++)
{
bool ff = 0;
for(ri j = i; j <= n; j ++)
{
num[v[j]] ++;
if(num[v[j]] > 1)
{
ff = 1;
for(ri k = j; k >= i; k --)
num[v[k]] --;
break;
}
for(ri k = j + 1; k <= n; k ++)
{
bool f = 0;
for(ri l = k; l <= n; l ++)
{
num[v[l]] ++;
if(num[v[l]] > 1)
{
for(ri a = l; a >= k; a --)
num[v[a]] --;
f = 1;
break;
}
else if(ans < j - i + 1 + l - k + 1)
{
ans = max(ans, j - i + 1 + l - k + 1); ci ++;
//cout << i << ' ' << j << ' ' << k << ' ' << l << '\n';
}
}
if(f == 0)
{
for(ri l = n; l >= k; l --)
num[v[l]] --;
}
}
}
if(ff == 0)
{
for(ri j = n; j >= i; j --)
num[v[j]] --;
}
}
/*for(ri i = 1; i <= tot; i ++)
for(ri j = i + 1; j <= tot; j ++)
for(ri a = ter[i].l; a <= ter[i].r; a ++)
{
for(ri b = a; b <= ter[i].r; b ++)
{
num[v[b]] ++;
for(ri c = ter[j].l; c <= ter[j].r; c ++)
{
if(c >= a && c <= b)
continue;
bool f = 0;
for(ri d = c; d <= ter[j].r; d ++)
{
if(d >= a && d <= b)
{
for(ri e = d - 1; e >= c; e --)
num[v[e]] --;
f = 1; break;
}
num[v[d]] ++;
if(num[v[d]] > 1)
{
for(ri e = d; e >= c; e --)
num[v[e]] --;
f = 1; break;
}
else
ans = max(ans, b - a + 1 + d - c + 1), ci ++;
}
if(f == 0)
{
for(ri d = ter[j].r; d >= c; d --)
num[v[d]] --;
}
}
}
for(ri e = ter[i].r; e >= a; e --)
num[v[e]] --;
}*/
printf("%d", ans);
fclose(stdin);
fclose(stdout);
return 0;
}
std代码
#include<bits/stdc++.h>
#define debug(x) cout<<#x<<"="<<x<<endl
using namespace std;
const int maxn = 2009;
int t[maxn],a[maxn],cnt[maxn];
bool vis[maxn];
int n,T,tot,ans,poi;
pair<int,int> b[maxn];
vector<int> pos[maxn];
set<pair<int,int> > S;
set<pair<int,int> >::iterator it,tmp;
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
int getans()
{
while(!cnt[poi]&&poi) poi--;
if(poi==0) return 0;
return poi;
}
void work(int x)
{
it=S.lower_bound(make_pair(x+1,0));
if(it==S.begin()) return ;
it--;
int L=x,R=x;
while(true)
{
if((*it).second<x) break;
int l=(*it).first,r=(*it).second;
cnt[r-l+1]--;
L=min(L,l);R=max(R,r);
if(it==S.begin()){S.erase(it);break;}
tmp=it;it--;S.erase(tmp);
}
if(L<x)
{
pair<int,int> line=make_pair(L,x-1);
if(S.find(line)==S.end()) S.insert(line),cnt[x-L]++;
}
if(x<R)
{
pair<int,int> line=make_pair(x+1,R);
if(S.find(line)==S.end()) S.insert(line),cnt[R-x]++;
}
}
void ClearLove()
{
for(int i=1;i<=tot;i++) pos[i].clear();
ans=tot=0;
}
int main()
{
freopen("holyshit.in","r",stdin);
freopen("holyshit.out","w",stdout);
T=1;
for(int I=1;I<=T;I++)
{
n=read();ClearLove();
for(int i=1;i<=n;i++) a[i]=t[i]=read();
sort(t+1,t+1+n);tot=unique(t+1,t+1+n)-t-1;
for(int i=1;i<=n;i++) a[i]=lower_bound(t+1,t+1+tot,a[i])-t,pos[a[i]].push_back(i);
for(int i=1;i<=n;i++)
{
memset(vis,0,sizeof vis);
int now=i;vis[a[now]]=1;
while(!vis[a[now+1]]&&now<n) now++,vis[a[now]]=1;
b[i]=make_pair(i,now);
}
for(int i=1;i<=n;i++)
{
memset(vis,0,sizeof vis);
memset(cnt,0,sizeof cnt);
S.clear();poi=n;
for(int j=i+1;j<=n;j++) S.insert(b[j]),cnt[b[j].second-b[j].first+1]++;
for(int j=i;j>=1;j--)
{
int x=a[j],sz=pos[x].size();
if(vis[x]) break;vis[x]=1;
for(int k=0;k<sz;k++)
{
int p=pos[x][k];
work(p);
}
ans=max(ans,i-j+1+getans());
}
}
printf("%d\n",ans);
}
return 0;
}