首页 > 其他分享 >Solution Set - APIO2014

Solution Set - APIO2014

时间:2023-04-04 21:13:19浏览次数:56  
标签:tmp Set val int Solution APIO2014 mid -- dp

目录


A 回文串

给定字符串 \(S\)。对 \(S\) 的所有回文子串,求其长度与出现次数之积的最大值。

\(|S| \le 300000\)。


点击查看代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int N=3e5+5;
int n,m,a[N<<1],lg2[N],cnt,str[N<<2][2];
int S,x[N],y[N],c[N],sa[N],rk[N],h[N],mn[N][25];
ll ans;char s[N],t[N<<1];
void SA(){
	S=300;
	for(int i=1;i<=n;i++){x[i]=s[i];++c[x[i]];}
	for(int i=2;i<=S;i++)c[i]+=c[i-1];
	for(int i=n;i>=1;i--)sa[c[x[i]]--]=i;
	for(int k=1;k<=n;k<<=1){
		int num=0;
		for(int i=n-k+1;i<=n;i++)y[++num]=i;
		for(int i=1;i<=n;i++)if(sa[i]>k)y[++num]=sa[i]-k;
		for(int i=1;i<=S;i++)c[i]=0;
		for(int i=1;i<=n;i++)c[x[i]]++;
		for(int i=2;i<=S;i++)c[i]+=c[i-1];
		for(int i=n;i>=1;i--){sa[c[x[y[i]]]--]=y[i];y[i]=0;}
		for(int i=1;i<=n;i++)swap(x[i],y[i]);
		num=1;x[sa[1]]=1;
		for(int i=2;i<=n;i++){
			if(y[sa[i]]==y[sa[i-1]]&&y[sa[i]+k]==y[sa[i-1]+k])
				x[sa[i]]=num;
			else x[sa[i]]=++num;
		}
		if(num==n)break;S=num;
	}
}
void LCP(){
	int k=0;
	for(int i=1;i<=n;i++)rk[sa[i]]=i;
	for(int i=1;i<=n;i++){
		if(rk[i]==1)continue;
		if(k)k--;
		int j=sa[rk[i]-1];
		while(i+k<=n&&j+k<=n&&s[i+k]==s[j+k])k++;
		h[rk[i]]=k;
	}
}
void build_ST(){
	for(int i=1;i<=n;i++)mn[i][0]=h[i];
	for(int j=1;(1<<j)<=n;j++)
		for(int i=1;i<=n-(1<<j)+1;i++)
			mn[i][j]=min(mn[i][j-1],mn[i+(1<<j-1)][j-1]);
}
int query(int l,int r){
	if(l>r)return 0;
	int i=lg2[r-l+1];int j=(1<<i);
	return min(mn[l][i],mn[r-j+1][i]);
}
void Manacher(){
	int l=1,r=0;
	for(int i=1;i<=m;++i){
		if(r>=i&&i+a[l+r-i]<=r)a[i]=a[l+r-i];
		else{
			int k=max(0,r-i);
			while(i+k<=m&&i-k>=1&&t[i+k]==t[i-k]){
				++k;++cnt;
				str[cnt][0]=(i-k+2)/2;str[cnt][1]=(i+k-1)/2;
				if(str[cnt][0]>str[cnt][1])--cnt;
			}
			a[i]=k;l=i-k+1;r=i+k-1;
		}
	}
}
ll solve(int l,int r){
	int L=0,R=0,p1=0,p2=0;
	L=2;R=rk[l];p1=rk[l]+1;
	while(L<=R){
		int mid=L+R>>1;
		if(query(mid,rk[l])>=r-l+1)p1=mid,R=mid-1;
		else L=mid+1;
	}
	L=rk[l]+1;R=n;p2=rk[l];
	while(L<=R){
		int mid=L+R>>1;
		if(query(rk[l]+1,mid)>=r-l+1)p2=mid,L=mid+1;
		else R=mid-1;
	}
	return 1ll*(p2-p1+2)*(r-l+1);
}
int main(){
	scanf("%s",s+1);
	n=strlen(s+1);m=2*n+1;t[1]='#';
	for(int i=0;(1<<i)<=n;i++)lg2[1<<i]=i;
	for(int i=1,lst=0;i<=n;i++){
		if(lg2[i])lst=lg2[i];
		else lg2[i]=lst;
	}
	for(int i=n;i>=1;--i)t[2*i]=s[i],t[2*i+1]='#';
	Manacher();SA();LCP();build_ST();
	for(int i=1;i<=cnt;i++)ans=max(ans,solve(str[i][0],str[i][1]));
	printf("%lld\n",ans);
	return 0;
}

B 序列分割

将长为 \(n\) 的数组分 \(k\) 次,每次在某一段内部将其分成两段,得分是分出两段的元素和的乘积。\(k\) 次操作的总得分是每次得分之和。求最大得分并输出方案。

\(n \le 100000\),\(k \le 200\),\(k \lt n\)。


点击查看代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+5,K=205;
int n,k,lst[K][N];
ll dp[K][N],s[N],b[N],sum;
int q[N],he,ta;
int main(){
	scanf("%d%d",&n,&k);
	for(int i=1,x;i<=n;i++){
		scanf("%d",&x);
		s[i]=s[i-1]+x;sum+=x;
	}
	memset(dp,0x3f,sizeof(dp));
	for(int j=1;j<=n;j++)dp[1][j]=s[j]*s[j];
	for(int i=2;i<=k+1;i++){
		he=ta=1;q[1]=i-1;
		b[i-1]=s[i-1]*s[i-1]+dp[i-1][i-1];
		for(int j=i;j<=n;j++){
			while(he<ta&&(b[q[he+1]]-b[q[he]])<=2*s[j]*(s[q[he+1]]-s[q[he]]))++he;
			dp[i][j]=s[j]*s[j]-2*s[q[he]]*s[j]+b[q[he]];lst[i][j]=q[he];
			b[j]=s[j]*s[j]+dp[i-1][j];
			while(ta>he&&(b[j]-b[q[ta-1]])*(s[j]-s[q[ta]])>=
						 (b[j]-b[q[ta]])*(s[j]-s[q[ta-1]]))--ta;
			q[++ta]=j;
		}
	}
	printf("%lld\n",(sum*sum-dp[k+1][n])/2);
	for(int i=k,j=lst[k+1][n];i>=1;i--){
		printf("%d ",j);
		j=lst[i][j];
	}
	return 0;
}

C 连珠线

初始有一个点,用如下两种操作生成一棵树:

Append(w, v):一个新的点 \(w\) 和一个已经添加的点 \(v\) 用红边连接起来。

Insert(w, u, v):一个新的点 \(w\) 插入到用红边连起来的两个点 \(u, v\) 之间。具体过程是删去 \(u, v\) 之间红边,分别用蓝边连接 \(u, w\) 和 \(w, v\)。

给定 \(n\) 个点的最终状态。求蓝边权值之和的最大可能值。

\(n \le 200000\)。


点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+5,INF=1<<29;
int n,dp[N][2],g[N][2],ans;
int head[N],nxt[N<<1],ver[N<<1],val[N<<1],tot;
int max(int a,int b){return a>b?a:b;}
void add(int u,int v,int w){
	ver[++tot]=v;
	val[tot]=w;
	nxt[tot]=head[u];
	head[u]=tot;
}
void dfs(int u,int fa){
	dp[u][0]=0;g[u][0]=g[u][1]=-INF;
	for(int i=head[u];i;i=nxt[i]){
		int v=ver[i];
		if(v==fa)continue;
		dfs(v,u);
		int tmp=max(dp[v][0],dp[v][1]+val[i]);
		dp[u][0]+=tmp;
		tmp=dp[v][0]+val[i]-tmp;
		if(tmp>g[u][0])g[u][1]=g[u][0],g[u][0]=tmp;
		else if(tmp>g[u][1])g[u][1]=tmp;
	}
	dp[u][1]=g[u][0]+dp[u][0];
}
void redfs(int u,int fa,int in){
	for(int i=head[u];i;i=nxt[i]){
		int v=ver[i];
		if(v==fa)continue;
		int t0=dp[u][0],t1=dp[u][1],t2=dp[v][0],t3=dp[v][1];
		int tmp=max(dp[v][0],dp[v][1]+val[i]);
		dp[u][0]=dp[u][0]-tmp;
		if(g[u][0]==val[i]+dp[v][0]-tmp)dp[u][1]=dp[u][0]+max(in,g[u][1]);
		else dp[u][1]=dp[u][0]+max(in,g[u][0]);
		tmp=max(dp[u][0],dp[u][1]+val[i]);
		dp[v][0]=dp[v][0]+tmp;
		dp[v][1]=dp[v][0]+max(g[v][0],val[i]+dp[u][0]-tmp);
		ans=max(ans,dp[v][0]);
		redfs(v,u,val[i]+dp[u][0]-tmp);
		dp[u][0]=t0;dp[u][1]=t1;dp[v][0]=t2;dp[v][1]=t3;
	}
}
int main(){
	scanf("%d",&n);
	for(int i=1,u,v,w;i<n;i++){
		scanf("%d%d%d",&u,&v,&w);
		add(u,v,w);add(v,u,w);
	}
	dfs(1,-1);ans=dp[1][0];
	redfs(1,-1,-INF);
	printf("%d\n",ans);
	return 0;
}

标签:tmp,Set,val,int,Solution,APIO2014,mid,--,dp
From: https://www.cnblogs.com/by-chance/p/17287907.html

相关文章

  • 数据结构之Set | 让我们一块来学习数据结构
    数组(列表)、栈、队列和链表这些顺序数据结构对你来说应该不陌生了。现在我们要学习集合,这是一种不允许值重复的顺序数据结构。我们将要学到如何创建集合这种数据结构,如何添加和移除值,如何搜索值是否存在。你也会学到如何进行并集、交集、差集等数学运算。本章内容包括:从头创建一个S......
  • js中e.clientX e.pageX e.offsetX e.screenX之间的区别
     event.clientX、event.clientY鼠标相对于浏览器窗口可视区域的X,Y坐标(窗口坐标),可视区域不包括工具栏和滚动条。IE事件和标准事件都定义了这2个属性event.pageX、event.pageY类似于event.clientX、event.clientY,但它们使用的是文档坐标而非窗口坐标。这2个属性不是标准属性,但......
  • mysql中find_in_set()函数的使用
    首先举个例子来说: 有个文章表里面有个type字段,它存储的是文章类型,有1头条、2推荐、3热点、4图文等等。现在有篇文章他既是头条,又是热点,还是图文,type中以1,3,4的格式存储。那我们如何用sql查找所有type中有4的图文类型的文章呢?? 这就要我们的find_in_set出马的时候到了。......
  • Grafana--Min step与Resolution
    问题:今天在统计机房请求量的时候,发现时间选择12hours时还是正常的,但是选择24hours时就有一些线条出不来,数据也有缺失,如下:12hours 24hours 问了同事,说是数据量太多,导致线条失真,可以改大步长(step),然后去百度了下step,没看懂... 先记录下现象,后面再研究吧 原因:百......
  • Chisel3 使用 DPI-C,发现在 Chisel 环境下 printf 没问题,但是 set_pc 死活传不到 cpp
    大概率是因为你使用了SignExt之类的封装这类封装只会把”值“传给DPI-C,而不会把线连给DPIC,即,传过去的是调用set_pc时的值,而不是引用这样会造成CPP获取不了相应线路的指针 如下图     这些也是错的......
  • Unity升级后打包AssetBundle变慢
    1)Unity升级后打包AssetBundle变慢​2)打包使有些资源合成了一个资源data.unity3d,有些分开的原因3)Unreal在移动设备中无法使用Stat命令获取到GPUThread的耗时4)Unity中如何看到相机视野范围内的剔除结果这是第330篇UWA技术知识分享的推送,精选了UWA社区的热门话题,涵盖了UWA问答、社......
  • vim setting
    /etc/vim/vimrcsetnocompatible"usevimdefaultssetbackspace=2"makebackspacelikemostotherappssetls=2"allwaysshowstatuslinesettabstop=5"numbersofspacesoftabcharactersetshiftwidth=5......
  • thread promise get_future(),get(), promise set_value()
    #include<chrono>#include<ctime>#include<future>#include<iomanip>#include<iostream>#include<sstream>#include<string>#include<thread>#include<unistd.h>#include<uuid/uuid.h>std:......
  • AirCassette音乐应用:复古情愫与现代社交元素的完美融合
    随着iPod和iPhone等现代设备的涌现,音乐已变得无处不在。在享受数字音乐带来的轻松体验时,是否也会偶尔怀念那个老式随身听和磁带的年代?AirCassette就是这样一款融合了怀旧情感和现代社交元素的iOS音乐应用。通过这款时尚的应用,用户可在播放数字音乐时体验磁带带来的视觉享受,同时......
  • (4.3)数组、对象及类数组对象,set的用法,正则表达式的常用方法,蓝桥杯备赛-(生成数组、数
    1.1数组、对象及类数组对象1.数组:​ 数组是有序的数据集合,其中的索引值从0开始递增,并且数组有length属性,可以获取数组内的元素个数,其中的值可以是任何的数组类型。2.对象:​ 对象是无序的是由一个或多个键值对组成的数据集合,对象没有length属性。3.伪数组(类数组对象):​ ......