BZOJ3072 : [Pa2012]Two Cakes

考虑DP,设$f[i][j]$表示考虑了$a[1..i]$和$b[1..j]$的最小代价。

若$a[i]==b[j]$,则$f[i][j]=\min(f[i-1][j],f[i][j-1])+1$。

否则找到最大的$t$,满足$x$和$y$往前$t$个均不相等,此时$f[i][j]=f[i-t-1][j-t-1]+t$。

对于$t$,可以通过在相应差值的序列中二分查找得到。

对于DP的计算,可以通过搜索,并将那$n$个$a[i]==b[j]$的状态记忆化。

因为对于每个没有记忆化的状态,均可以在$O(\log n)$的时间内转化为那$n$个状态,所以总时间复杂度为$O(n\log n)$。

#include<cstdio>
const int N=1000010,BUF=13778000;
int n,m,i,j,a[N],b[N],c[N],f[N],g[N<<1],nxt[N],st[N<<1],en[N<<1],q[N];char Buf[BUF],*buf=Buf;
inline void read(int&a){for(a=0;*buf<48;buf++);while(*buf>47)a=a*10+*buf++-48;}
inline void add(int x,int y){nxt[y]=g[x];g[x]=y;}
inline int min(int a,int b){return a<b?a:b;}
inline int pre(int l,int r,int x){
  int t=0,mid;
  while(l<=r)if(q[mid=(l+r)>>1]<=x)l=(t=mid)+1;else r=mid-1;
  return q[t];
}
int dp(int x,int y){
  if(!x||!y)return x+y;
  if(a[x]==b[y])return f[x]?f[x]:f[x]=min(dp(x-1,y),dp(x,y-1))+1;
  int t=pre(st[x-y+n],en[x-y+n],x);
  return t?dp(t,y-x+t)+x-t:(x>y?x:y);
}
int main(){
  fread(Buf,1,BUF,stdin);read(n);
  for(i=1;i<=n;i++)read(a[i]);
  for(i=1;i<=n;i++)read(b[i]),c[b[i]]=i;
  for(i=n;i;i--)add(i-c[a[i]]+n,i);
  for(i=1;i<n+n;en[i++]=m)for(st[i]=m+1,j=g[i];j;j=nxt[j])q[++m]=j;
  return printf("%d",dp(n,n)),0;
}

  

时间: 2024-11-05 22:05:40

BZOJ3072 : [Pa2012]Two Cakes的相关文章

【BZOJ3072】[Pa2012]Two Cakes【DP】

[题目链接] 题解: 很容易想到O(n^2)DP的做法. (1)A[i] == B[j],dp[i][j] = min(dp[i - 1][j], dp[i][j - 1]) + 1 (2)A[i] != B[j],dp[i][j] = dp[i - t + 1][j - t + 1] + t,t表示最长的一段不相等的数的长度 发现如果连续的一段内要填写的两个数都不相同,那么一定是贪心转移的,即只有数字相同的地方需要DP. 如何快速找到t? 考虑全排列每个数字只出现了一次,可以得出相同数字的位置

【BZOJ3502/2288】PA2012 Tanie linie/【POJ Challenge】生日礼物 堆+链表(模拟费用流)

[BZOJ3502]PA2012 Tanie linie Description n个数字,求不相交的总和最大的最多k个连续子序列. 1<= k<= N<= 1000000. Sample Input 5 2 7 -3 4 -9 5 Sample Output 13 题解:跟1150和2151差不多. 我们先做一些预处理,因为连续的正数和连续的负数一定是要么都选要么都不选,所以可以将它们合并成一个数,同时区间中的零以及左右两端的负数没有意义,可以将它们删掉.然后我们得到的序列就变成:正-

hdu 5997 rausen loves cakes(线段数合并+启发式修改)

题目链接:hdu 5997 rausen loves cakes 题意: 给你n个点,每个点有一个颜色,现在有两个操作,第一个操作,将颜色x改为颜色y,第二个操作,询问[x,y]区间有多少颜色段(颜色段的定义为从左往右相同的颜色为一段,遇到不相同的为下一段,ie:144112为4段颜色) 题解: 对于第二个操作我们可以写一个线段树合并来搞定,对于第一个操作,就要用启发式修改来进行,如何启发式? 我们开一个数组来记录每个颜色对应的颜色,最开始都是对应自己,然后开一个vector来记录每个颜色的位置

BZOJ4289 : PA2012 Tax

一个直观的想法是把每条边拆成两条有向边,同时每条有向边是新图中的一个点.对于两条边a->b与b->c,两点之间连有向边,费用为两条边费用的最大值.然后新建源点S与汇点T,由S向所有起点为1的边连边,T接受所有终点为n的边,那么答案就是S到T的最短路. 这样子的边数为$O(m^2)$,不能承受. 考虑枚举中转点x,将所有与它有关的边按费用从小到大排序.对于每条边,从以x为终点的点向以x为起点的点连边,费用为该边的费用.从以x为起点的点向下一条边连边,费用为两条边费用的差值,向上一条边连边,费用为

bzoj4232: [Neerc2011 Northern]Kids Like Cakes

Description 给定一个n个点的严格凸多边形(各个内角<180°),现在要切出两个非退化三角形(三点不共线),要求两个三角形顶点必须是凸多边形的顶点,且三角形不可相交(但是点或边可以重合).求两个三角形面积之差的最大值. Input 第一行,一个整数N. 第二到N+1行,每行两个整数xi,yi,表示多边形的一个点,保证顶点按顺时针或逆时针顺序给出. Output 输出答案,精确到小数点后1位. 最小三角形一定是相邻三点构成,因此只需枚举每个最小三角形,查询剩余部分中的最大三角形 dp,f

BZOJ 3498: PA2009 Cakes

Description \(n\)个点\(m\)条边,求所有三元环,一个三元环的贡献为三个点中权值最大的点.\(n\leqslant 1\times 10^5,n\leqslant 2.5\times 10^5\) Solution 分类讨论. 只从权值大的点连向权值小的点,因为可能权值相同,顺序需要确定下来. 枚举所有边. 如果一个点的度数小于等于\(\sqrt m\)那么枚举所有的点,看看他和另一个点有没有连边,直接用map存一下... 如果度数大于\(\sqrt m\)那么枚举另一个点的所

bzoj3502[PA2012]Tanie Linie(最大k区间和)

题意:给定一个长为n的数列,要求选出最多k个不相交的区间(可以不选),使得选中的数字之和最大.(1<=k<=n<=1000000)分析:首先我们通过预处理对问题做一些简化.原序列中的0对答案没有影响,可以直接删掉.连续的一段正数或一段负数一定是都选或者都不选,可以合并成一个数字.这样把序列转化成了正数和负数交替出现的形式.如果序列的最左端/最右端是负数,这个负数在最优解当中一定不会被选中,我们可以把它删掉.这样就把序列变成了正负交替,以正数开头和结尾的形式.这时若直接考虑选出k个不相交区

●BZOJ 4289 PA2012 Tax

●赘述题目 算了,题目没有重复的必要. 注意理解:对答案造成贡献的是每个点,就是了. 举个栗子: 对于如下数据: 2 1 1 2 1 答案是 2: ●题解 方法:建图(难点)+最短路. 先来几个链接:(他们为我解题提供了思路,但有些部分看得我有点mengbi) ●http://blog.csdn.net/pure_w/article/details/55060079 ●http://www.cnblogs.com/clrs97/p/5046933.html 建图: 1.把原图的双向边拆成两条单向

【BZOJ】3502 PA2012 Tanie linie

[算法] [题解] 胡策k≤10的环状DP做法: 1.钦定法:先确定第一位(可能和第n位)的状态,然后后面正常做DP,显然正确答案是一定会被记录的,因为从整体上看不会有影响. 2.环的特性:取的段和不取的段数量相等,位置互补.所以1和n的连接处都选或都不选都会有不被包括的情况,一选一不选就和链一样了. 正解贪心: 因为相邻的正数或相邻的负数肯定是要选一起选,所以点缩成正负正负-的数列形式,那么考虑先选择全部正的. 如果选择的段数过多,考虑删除则有两种选择:舍弃一个正数(相当于舍弃一个正数和两个负