ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

【CF1129D】Isolation(分块优化DP)

2022-01-28 15:35:18  阅读:159  来源: 互联网

标签:CF1129D 元素 个数 恰好 && Isolation tg DP define


题目链接

  • 给定一个长度为 \(n\) 的序列,求有多少种方案将它划分成若干段,使得每一段中出现恰好一次的元素不超过 \(k\) 个。
  • \(1\le n\le10^5\)

分块优化 DP

容易想到设 \(f_i\)表示以 \(i\) 为一段结尾时的答案。

那么从 \(j\) 能转移到 \(i\),根据题目的要求,充要条件是 \((j,i]\) 中出现恰好一次的元素个数不超过 \(k\)。

由于我们是在从小到大枚举 \(i\) 转移的,因此只要考虑如何在这一过程中维护 \((j,i]\) 中出现恰好一次的元素个数,即每次考虑 \(a_i\) 对于这一数值的影响。

所以找到 \(a_i\) 上次出现的位置 \(p1\) 和上上次出现的位置 \(p2\),则对 \(j\in[p2,p1)\) 在 \((j,i]\) 中出现恰好一次的元素个数减少 \(1\),对 \(j\in[p1,i)\) 在 \((j,i]\) 中出现恰好一次的元素个数增加 \(1\),其余位置不受影响。

一般的数据结构难以维护这种东西,因此考虑分块。具体地,散块修改直接暴力重构,整块修改只要用桶存一下出现恰好一次的元素个数为每种数值的 \(f_i\) 之和,就可以快速更新信息了。

代码:\(O(n\sqrt n)\)

#include<bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define Rg register
#define RI Rg int
#define Cn const
#define CI Cn int&
#define I inline
#define W while
#define N 100000
#define SN 320
#define INF 1e9
#define X 998244353
#define Inc(x,y) ((x+=(y))>=X&&(x-=X))
#define Dec(x,y) ((x-=(y))<0&&(x+=X))
using namespace std;
namespace FastIO
{
	#define FS 100000
	#define tc() (FA==FB&&(FB=(FA=FI)+fread(FI,1,FS,stdin),FA==FB)?EOF:*FA++)
	char oc,FI[FS],*FA=FI,*FB=FI;
	Tp I void read(Ty& x) {x=0;W(!isdigit(oc=tc()));W(x=(x<<3)+(x<<1)+(oc&15),isdigit(oc=tc()));}
	Ts I void read(Ty& x,Ar&... y) {read(x),read(y...);}
}using namespace FastIO;
int n,k,f[N+5],p1[N+5],p2[N+5];
namespace Block//分块
{
	int sz,bl[N+5];I void Bd() {sz=sqrt(n);for(RI i=0;i<=n;++i) bl[i]=i/sz+1;}
	int tot,c[N+5],tg[SN],g[SN][N+5];I void BF(CI l,CI r,CI v)//暴力修改
	{
		RI i,o=bl[l];for(i=(o-1)*sz;i<=min(o*sz-1,n);++i) c[i]+tg[o]<=k&&Dec(tot,f[i]),g[o][c[i]]=0;for(i=l;i<=r;++i) c[i]+=v;//删除原有信息并修改
		for(i=(o-1)*sz;i<=min(o*sz-1,n);++i) (c[i]+=tg[o])<=k&&Inc(tot,f[i]),Inc(g[o][c[i]],f[i]);tg[o]=0;//加入新信息
	}
	I void U(CI l,CI r,CI v)//修改
	{
		RI L=bl[l],R=bl[r];if(L==R) return (void)BF(l,r,v);BF(l,L*sz-1,v),BF((R-1)*sz,r,v);//散块暴力
		for(RI i=L+1;i<R;++i) tg[i]+=v,~v?k+1-tg[i]>=0&&Dec(tot,g[i][k+1-tg[i]]):k-tg[i]>=0&&Inc(tot,g[i][k-tg[i]]);//整块利用维护出的桶快速更新信息
	}
	I void Ins(CI x) {c[x]<=k&&Inc(tot,f[x]),Inc(g[bl[x]][c[x]],f[x]);}//添加一个新位置
}using namespace Block;
int main()
{
	RI i,x;for(read(n,k),Bd(),f[0]=1,Ins(0),i=1;i<=n;++i)
		read(x),p1[x]&&(U(p2[x],p1[x]-1,-1),p2[x]=p1[x]),U(p1[x],i-1,1),p1[x]=i,f[i]=tot,Ins(i);//修改后转移
	return printf("%d\n",f[n]),0;
}

标签:CF1129D,元素,个数,恰好,&&,Isolation,tg,DP,define
来源: https://www.cnblogs.com/chenxiaoran666/p/CF1129D.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有