CodeForces 425C Sereja and Two Sequences

题意:

两组数字a和b  如果a[i]等于b[j]  则可将a[i]和b[j]前所有数字删掉  这种操作花费e体力  得到1元钱  或者一次删掉所有数字  这种操作花费等于曾经删除的所有数字个数  做完后得到所有钱  问 一共s体力 可以得到多少钱

思路:

dp+二分

由数据可知最多拿到300元钱  因此可以定义  dp[i][j]表示有i元钱时  b串删除到了j处时  a串删到的位置

状态转移为 dp[i][j] = lower_bound ( a[j] , dp[i-1][j-1] + 1 )  意思是a[j]与dp[i-1][j-1]后的第一个相同的数字匹配 (可以这么做的原因是  保证第二种操作的花费最小  同时留下尽量多的数字供后面使用)

代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
#define N 100010
#define inf (1U<<31)-1

int n,m,s,e,ans;
int a[N],b[N],dp[305][N];
vector<int> ed[N];

int main()
{
    int i,j,k;
    scanf("%d%d%d%d",&n,&m,&s,&e);
    for(i=1;i<=n;i++) scanf("%d",&a[i]);
    for(j=1;j<=m;j++)
    {
        scanf("%d",&b[j]);
        ed[b[j]].push_back(j);
    }
    for(i=0;i<N;i++) ed[i].push_back(inf);
    memset(dp,-1,sizeof(dp));
    memset(dp[0],0,sizeof(dp[0]));
    for(i=1;i<=s/e;i++)
    {
        for(j=1;j<=n;j++)
        {
            if(dp[i-1][j-1]!=-1)
            {
                dp[i][j]=dp[i][j-1];
                k=lower_bound(ed[a[j]].begin(),ed[a[j]].end(),dp[i-1][j-1]+1)-ed[a[j]].begin();
                k=ed[a[j]][k];
                if(k==inf) continue;
                if(dp[i][j]==-1||dp[i][j]>k) dp[i][j]=k;
                if(dp[i][j]+j+i*e<=s) ans=max(ans,i);
            }
        }
    }
    printf("%d\n",ans);
    return 0;
}

CodeForces 425C Sereja and Two Sequences

时间: 2024-12-27 20:51:39

CodeForces 425C Sereja and Two Sequences的相关文章

Codeforces Round #243 (Div. 1)——Sereja and Two Sequences

题目链接 题意:给两个长度分别为n和m的序列,现在有两种操作:1.分别选择两个序列的一个非空前缀,切两个前缀的最后一位相同,删除之,得到1分(只累计),消耗e:2.直接删除两个序列,消耗值定于两个序列之前删除的元素个数之和,并且使得得到的分有效(之前没有有效分) 分析: 首先,问题其实就是转化成,进行若干次操作1,然后进行操作2 还要找到一个判别标准,来评判较优的状态(贪心) 每次的消耗值比较大,其实可以计算出最大的删除次数,这个值不是很大 状态表示: 简单的,一个状态可以表示为串A的位置.串B

[2016-04-13][codeforces][447][C][DZY Loves Sequences]

时间:2016-04-13 23:39:47 星期三 题目编号:[2016-04-13][codeforces][447][C][DZY Loves Sequences] 题目大意:给定一串数字,问改变其中一个数字之和,最长能得到多长的严格增加的子串 分析: 维护每个数字往左和往右能延续多长(严格减,增),然后枚举每个点, 如果这个点已经在一个严格增加的序列中,那么ans =min(n, max(ans , l[i] + r[i] + 1)) 即左右两边延伸之后,改变后面非递增的一个数字 注意这

CodeForces 380A Sereja and Prefixes

A. Sereja and Prefixes time limit per test 1 second memory limit per test 256 megabytes input standard input output standard output Sereja loves number sequences very much. That's why he decided to make himself a new one following a certain algorithm

codeforces#FF(div2) DZY Loves Sequences

n个数,可以任意改变其中一个数,求最长的上升子区间长度 思路:记录一个from[i]表示从位置i的数开始最长的上升区间长度 记录一个to[i]表示到位置i的数所能达到的最长上升区间长度 枚举要改变的数的位置i,此时能达到的长度为to[i - 1] + from[i + 1] + 1,取最大值 //#pragma comment(linker, "/STACK:102400000,102400000") //HEAD #include <cstdio> #include &l

CodeForces 425B Sereja and Table

题意: 一个充满0和1的矩形  最多将k个数字翻转  问  最少翻转几个数字可以使所有0或1的连通块都是矩形  如果不可能输出-1 思路: 首先  如果确定了一行  那么整个矩形就确定了 因为在最后的状态中  每一行要么与确定的行完全一致  要么完全相反  这才能保证连通块都是矩形 然后  本题k很小  因此可以分类讨论 如果 max(n,m)<=k 那么可以暴力枚举第一行状态  进而计算翻转次数  最多只有2^10种情况 否则 max(n,m)>k  那么至少有一行或者一列是没有被修改的  

CodeForces 425A Sereja and Swaps

题意: 一串数字  最多可以做k次交换数字  求  最大连续和是多少 思路: n^2暴力枚举所有区间  那么如果要换数字  一定是从区间外拿大数换区间内的小数  优先队列可以完成操作 代码: #include<cstdio> #include<cstring> #include<algorithm> #include<queue> using namespace std; #define N 201 int n,m,ans; int a[N]; priori

CodeForces 425D Sereja and Squares

题意: 平面上有n个点  问  最多能组成多少个边与坐标轴平行的正方形 思路: 这是一个通过不断二分查找乱搞的题- 首先枚举左下角  然后分别往上往右找左上角和右下角 这时如果发现边长不想等就通过长边长度在短边的方向二分查找最接近的值  不停往上往右延伸 如果发现边长想等了  那么要判断一下对应的左上角坐标出是不是有一个点 怎么判断呢  通过将所有点hash出一个值  然后二分- 反正这题就是各种二分乱搞 - -b  复杂度不好算  大概是n*(同x的点数+同y的点数) 代码: #include

codeforces 425B Sereja and Table(状态压缩,也可以数组模拟)

题目 给出一个n*m的01矩阵, 让你最多改变k个里面的值(0变1,1变0), 使得0.1的连通分量是矩阵.输出最少步数 1 ≤ n, m ≤ 100; 1 ≤ k ≤ 10 题解: 如果01连通分量是矩形, 那么矩形一定是这样的: 0101010 1010101 0101010 1010101 (上面的01代表子矩阵块). 也就是每一行要么是相同,要么是相反的. 如果n>k, 肯定有一行是不能改变的,那么枚举这一行,然后其余的要么变相同,要么变相反,看最少的步数. 如果n<k ,那么可以枚举

# codeforces 1272 F. Two Bracket Sequences(三维dp + bfs)

codeforces 1272 F. Two Bracket Sequences(三维dp + bfs) 题目大意 输入两个括号序列 s,t(不一定合法),你需要构造一个尽可能短的合法括号序列使得s,t 都是这个序列的子序列(子序列意味着不用连续) 解题思路 dp[i][j][k]表示匹配到s的第i个字符,匹配到t的第j个字符,并且此时(的个数比)多k个的时候的最小合法序列长度,k的上限是200(s和t中最多200个(或者)). 状态转移: 枚举答案合法序列的每一位是放置(或者) ? 放置(,如