#include<cstdio>#include<iostream>#include<set>#include<algorithm>#define RI register int#define CI const int&usingnamespace std;
constint N=200005,INF=2e9;
int t,n,a[N],rst[N],L[N],R[N]; set <int> pos[N];
inlineintgetL(CI x){
return L[x]==x?x:L[x]=getL(L[x]);
}
inlineintgetR(CI x){
return R[x]==x?x:R[x]=getR(R[x]);
}
intmain(){
for (scanf("%d",&t);t;--t)
{
scanf("%d",&n); longlong ans=0;
for (RI i=1;i<=n;++i) scanf("%d",&a[i]),rst[i]=a[i];
sort(rst+1,rst+n+1); int m=unique(rst+1,rst+n+1)-rst-1;
for (RI i=1;i<=n;++i) a[i]=lower_bound(rst+1,rst+m+1,a[i])-rst;
for (RI i=0;i<=n+1;++i) L[i]=R[i]=i;
for (RI i=1;i+1<=n;++i) if (a[i]==a[i+1]) L[i+1]=getL(i);
for (RI i=n-1;i>=1;--i) if (a[i]==a[i+1]) R[i]=getR(i+1);
for (RI i=1;i<=n;++i) if (getL(i)==i) pos[a[i]].insert(i);
for (RI i=1;i<=m;++i)
{
for (auto x:pos[i])
{
int l=getL(x),r=getR(x),vl=INF,vr=INF;
if (l-1>=1) vl=a[l-1];
if (r+1<=n) vr=a[r+1];
//printf("x = %d\n",x);//printf("l = %d; r = %d\n",l,r);//printf("vl = %d; vr = %d\n",vl,vr);if (vl==vr)
{
if (vl==INF) continue;
R[l-1]=getR(l); L[l]=getL(l-1);
L[r+1]=getL(r); R[r]=getR(r+1);
ans+=r-l+1; pos[vl].erase(r+1);
} elseif (vl<vr)
{
R[l-1]=getR(l); L[l]=getL(l-1);
ans+=r-l+1;
} else {
L[r+1]=getL(r); R[r]=getR(r+1);
ans+=r-l+1;
}
}
pos[i].clear();
}
printf("%lld\n",ans);
}
return0;
}
6|0G. The Median of the Median of the Median
刚开始犯病了一直想着直接算答案,而没有想到中位数的经典 trick 二分
考虑直接二分答案 x,不妨把 ≤x 的位置都置为 1,>x 的位置置为 −1
此时求 bl,r 的值就只用维护前缀和即可,此时得到每个 bl,r 和 x 的大小关系
同理,求 cl,r 时就等价于一个二维前缀和的过程,此时得到每个 cl,r 和 x 的大小关系
最后再求 cl,r 的中位数即可得到检验 x 的方法,总复杂度 O(n2logn)
#include<cstdio>#include<iostream>#define RI register int#define CI const int&usingnamespace std;
constint N=2005;
int n,r[N],a[N],pfx[N],sum[N][N];
inlineboolcheck(CI x){
for (RI i=1;i<=n;++i) a[i]=(r[i]<=x);
for (RI i=1;i<=n;++i) pfx[i]=pfx[i-1]+a[i];
for (RI i=1;i<=n;++i) for (RI j=i;j<=n;++j)
{
int ones=pfx[j]-pfx[i-1];
sum[i][j]=(ones*2>=j-i+1);
}
for (RI i=n;i>=1;--i) for (RI j=1;j<=n;++j)
sum[i][j]+=sum[i+1][j]+sum[i][j-1]-sum[i+1][j-1];
int cnt=0;
for (RI i=1;i<=n;++i) for (RI j=i;j<=n;++j)
if (sum[i][j]*2>=(j-i+1)*(j-i+2)/2) ++cnt;
return cnt*2>=n*(n+1)/2;
}
intmain(){
scanf("%d",&n);
for (RI i=1;i<=n;++i) scanf("%d",&r[i]);
int l=1,r=1e9,mid,ret; while (l<=r)
if (check(mid=l+r>>1)) ret=mid,r=mid-1; else l=mid+1;
returnprintf("%d",ret),0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!