子排列分析 解题报告

题目描述
其中,$n \leq 1e5 $
看到题,没有头绪;用脑子思考后,没有头绪。因此抛弃脑子,直接打暴力。
通过暴力算法,我们可以发现,符合条件的排列数量一定是严格不上升的
进一步研究发现:\([l,r]\) 不满足条件,则 \([l,r+1]\) 一定不满足条件。
下面是证明:已知 \([l,r]\) 不满足条件,那么一定存在二元组 \((i,j)\) 使得在 \(a_{i-l+1}<a_{j-l+1}\)\(a_i>a_j\)。那么对于 \([l,r+1]\),因为 \(l\) 没有变化,所以这样的二元组 \((i,j)\) 一定仍然存在,所以 \([l,r+1]\) 一定不符合条件。
通过暴力几组数据可以发现,对于绝大部分的数据,符合条件的子串不会很多,所以考虑对利用结论对暴力算法进行优化。
具体地,我们记录每一次符合条件子串的左端点,并在下一次匹配中只匹配以这些左端点开头的字串。当符合条件的子串个数为0时,马上退出循环。
启示:暴力出奇迹

#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
using namespace std;
inline int max(int x,int y){return x>y?x:y;}
const int N=1e5+100;
typedef long long ll;
int n,a[N],b[N],rk[N],rk0[N],cnt,pre[N],tot;
ll ans;
int main()
{
  freopen("sub.in","r",stdin);
  freopen("sub.out","w",stdout);
  scanf("%d",&n);
  for(int i=1;i<=n;i++) scanf("%d",a+i),pre[i]=i+1;
  tot=n-1;
  for(int len=1,old;len<=n;len++){
    if(tot==0) break;
    cnt=1;
    for(int k=1;k<=len;k++) b[k]=a[k];
    sort(b+1,b+len+1,less<int>());
    for(int k=1;k<=len;k++) rk0[b[k]]=k;
    old=tot,tot=0;
    for(int id=1;id<=old;id++){
      int i=pre[id];
      if(i+len-1>n) continue;
      for(int k=1;k<=len;k++) b[k]=a[i+k-1];
      sort(b+1,b+len+1,less<int>());
      for(int k=1;k<=len;k++) rk[b[k]]=k;
      bool flag=true;
      for(int k=1;k<=len;k++)
        if(rk[a[i+k-1]]!=rk0[a[k]]){
          flag=false;
          break;
        }
      if(flag){
        cnt++;
        pre[++tot]=i;
        //printf("[ %d , %d ]  ",i,j);
      }
    }
    ans=max(ans,1ll*cnt*len);
    //putchar('\n');
  }
  printf("%lld",ans);
  return 0;
}



posted @ 2025-07-07 16:29  XiaoZi_qwq  阅读(6)  评论(0)    收藏  举报