10.5清北刷题记

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颗棋全部放到棋盘上去,并且要求:

  1. 每个位置最多只能放一颗棋。
  2. 每行每列都恰好有2颗黑棋。
  3. 每行每列都恰好有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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值