CF180E Cubes 题解
CF180E Cubes 题解
首先把相邻的颜色相同的元素看成一个块,那么操作就是删除块之间的东西把若干个块拼在一起。
观察一下不难发现删除的元素一定是连续的,因为如果不连续那么只有一段区间是有用的,另一端区间就是白费了。
然后考虑枚举每个块,从第 \(i\) 个块的后面一个元素开始删。显然删的东西越多越好,就尽量把 \(k\) 次机会全用完。
于是就可以写出暴力的代码了。
#include<bits/stdc++.h>
using namespace std;
typedef long long ljl;
#define pb push_back
const int N=2e5+5,M=1e5+5;
int n,m,k,a[N],tot,ans;
vector<int> col[M];
struct NODE{
int l,r,c,p;
}node[N];
bool check()
{
for(int i=2;i<=n;++i)
if(a[i]!=a[1])return 0;
return 1;
}
int main(){
ios::sync_with_stdio(0);
cin>>n>>m>>k;
for(int i=1;i<=n;++i)cin>>a[i];
if(check()){cout<<n<<'\n';return 0;}
for(int i=1;i<=n;++i)
{
node[++tot].c=a[i];
node[tot].l=i;int j=i;
while(j<=n&&a[j]==a[i])++j;
node[tot].r=j-1;i=j-1;
ans=max(ans,node[tot].r-node[tot].l+1);
col[a[i]].pb(tot);
node[tot].p=(int)col[a[i]].size()-1;
}
for(int i=1,s;i<tot;++i)//在第i块后边开始删除
{
s=0;
int T=k,j=node[i].p,ls=(int)col[node[i].c].size();
for(;j<ls;++j)
{
int I=col[node[i].c][j],nxt=col[node[i].c][j+1];
s+=node[I].r-node[I].l+1;
if(j==ls-1)break;
T-=(node[nxt].l-1-node[I].r);
if(T<0)break;
}ans=max(ans,s);
}
cout<<ans<<'\n';
return 0;
}
然后交到 CF 上就会 TLE on test 45。
然而这题学长放 NOIP 模拟赛里了,结果不知道为啥给我 A 了……
然后考虑优化。
考虑前缀和,设 \(s_{i,j}\) 表示颜色为 \(i\),考虑到第 \(j\) 个块的两块之间的距离和。那么就是找到最后一个小于等于 \(k-s_{c_i,p-1}\) 的位置。
其中 \(c_i\) 表示块 \(i\) 的颜色,\(p\) 为第 \(i\) 块在所有颜色为 \(c_i\) 的块中的排名。
这显然可以用二分做。
然后就做完了。
Code:
#include<bits/stdc++.h>
using namespace std;
typedef long long ljl;
#define pb push_back
const int N=2e5+5,M=1e5+5;
ljl n,m,k,a[N],tot,ans;
vector<ljl> col[M];
vector<ljl> sum[M],s2[M];
struct NODE{
ljl l,r,c,p;
}node[N];
bool check()
{
for(int i=2;i<=n;++i)
if(a[i]!=a[1])return 0;
return 1;
}
ljl lwb(int cl,ljl L,ljl R,ljl c)//从sum[cl] [l~r] 中找到最后一个 <=c 的
{
int l=L,r=R,mid,ans=l;
while(l<=r)
{
mid=(l+r)/2;
if(sum[cl][mid]<=c)ans=mid,l=mid+1;
else r=mid-1;
}return ans;
}
int main(){
ios::sync_with_stdio(0);
cin>>n>>m>>k;
for(int i=1;i<=n;++i)cin>>a[i];
if(check()){cout<<n<<'\n';return 0;}
for(int i=1;i<=n;++i)
{
node[++tot].c=a[i];
node[tot].l=i;int j=i;
while(j<=n&&a[j]==a[i])++j;
node[tot].r=j-1;i=j-1;
ans=max(ans,node[tot].r-node[tot].l+1);
col[a[i]].pb(tot);
node[tot].p=(int)col[a[i]].size()-1;
}
for(int i=1;i<=m;++i)
{
ljl ls=(ljl)col[i].size();
if(!ls)continue;
for(int j=0;j<=ls;++j)sum[i].pb(0);
sum[i][1]=0;int lst=node[col[i][0]].r;
for(int j=1;j<ls;++j)
{
int l=node[col[i][j]].l,r=node[col[i][j]].r;
sum[i][j+1]=sum[i][j]+(l-1-lst);
lst=r;
}
}
for(int i=1;i<=m;++i)
{
int ls=(int)col[i].size();
if(!ls)continue;
for(int j=0;j<=ls;++j)s2[i].pb(0);
s2[i][0]=node[col[i][0]].r-node[col[i][0]].l+1;
for(int j=1;j<ls;++j)s2[i][j]=s2[i][j-1]+node[col[i][j]].r-node[col[i][j]].l+1;
}
for(int i=1;i<tot;++i)//在第i块后边开始删除
{
ljl s=0;int cl=node[i].c;
ljl j=node[i].p+1,ls=(int)col[cl].size();
ljl c=lwb(cl,j,ls,k+sum[cl][j]);
// for(int p=j-1;p<c;++p)s+=(node[col[cl][p]].r-node[col[cl][p]].l+1);
if(j>=2)
s=s2[cl][c-1]-s2[cl][j-2];
else s=s2[cl][c-1];
ans=max(ans,s);
}
cout<<ans<<'\n';
return 0;
}

浙公网安备 33010602011771号