Codeforces Round #459 (Div. 2) C 思维,贪心 D 记忆化dp

Codeforces Round #459 (Div. 2)

C. The Monster

题意:定义正确的括号串,是能够全部匹配的左右括号串。 给出一个字符串,有 (、)、 ? 三种字符, ? 可以当作 ( 可 ) 。 问这个字符串有多少个子串是正确的括号串。

tags:好考思维,想不到。。

预处理出每个字符向左向右最多可以匹配到哪里,再 O(n*n) 枚举所有区间,看是否符合条件。

//  C
#include<bits/stdc++.h>
using namespace std;
#pragma comment(linker, "/STACK:102400000,102400000")
#define rep(i,a,b) for (int i=a; i<=b; ++i)
#define per(i,b,a) for (int i=b; i>=a; --i)
#define mes(a,b)  memset(a,b,sizeof(a))
#define INF 0x3f3f3f3f
#define MP make_pair
#define PB push_back
#define fi  first
#define se  second
typedef long long ll;
const int N = 5005;

int len, l[N], r[N];
char s[N];
int main()
{
    scanf("%s", s+1);
    len = strlen(s+1);
    rep(i,1,len)
    {
        r[i] = len+1;
        int cnt = 0;
        rep(j,i,len)
        {
            if(s[j]==‘)‘) --cnt;
            else ++cnt;
            if(cnt<0) { r[i]=j; break; }
        }
    }
    per(i,len,1)
    {
        l[i] = 0;
        int cnt = 0;
        per(j,i,1)
        {
            if(s[j]==‘(‘) --cnt;
            else ++cnt;
            if(cnt<0) { l[i]=j; break; }
        }
    }
    ll  ans = 0;
    rep(i,1,len)
    {
        for(int j=i+1; j<=len; j+=2)
        {
            if(r[i]>j && l[j]<i) ++ans;
        }
    }
    printf("%lld\n", ans);

    return 0;
}

D. MADMAX

题意:给出一个DAG图,每条边有一个字母。两个人轮流走,每一次走过的边不能小于对方上一步走过的边。求两个人分别从点 i、j 出发,先手的胜负。

tags: dp[i][j][pre] 表示先手在点 i,后手在点 j ,且上一步的边是 pre 的情况下,先手胜就为 1,后手胜就为0 。

假设点 i 有边edge 可以到 to ,那么如果有 dp[j][to][edge] = 0,则 dp[i][j][pre] = 1 。

如果没有这样的点 to,那么  dp[i][j][pre] = 0。

当然,dp 肯定要记忆化的。

//  D
#include<bits/stdc++.h>
using namespace std;
#pragma comment(linker, "/STACK:102400000,102400000")
#define rep(i,a,b) for (int i=a; i<=b; ++i)
#define per(i,b,a) for (int i=b; i>=a; --i)
#define mes(a,b)  memset(a,b,sizeof(a))
#define INF 0x3f3f3f3f
#define MP make_pair
#define PB push_back
#define fi  first
#define se  second
typedef long long ll;
const int N = 105;

int n, m, G[N][N], dp[N][N][30], mx[N];
int solve(int i, int j, int pre)
{
    if(dp[i][j][pre]!=-1) return dp[i][j][pre];
    if(i==j)  return dp[i][j][pre]=0;
    if(mx[i]==-1) return dp[i][j][pre]=0;
    if(mx[i] > mx[j]) return dp[i][j][pre]=1;
    else
    {
        rep(to,1,n)
            if(G[i][to]!=-INF && G[i][to]>=pre)
            {
                if(solve(j, to, G[i][to])==0) return dp[i][j][pre]=1;
            }
    }
    return dp[i][j][pre]=0;
}
int main()
{
    scanf("%d%d", &n, &m);
    mes(dp, -1);  mes(mx, -1);
    rep(i,1,n) rep(j,1,n) G[i][j]=-INF;
    int u, v;  char ch;
    rep(i,1,m)
    {
        scanf("%d%d%*c%c", &u, &v, &ch);
        G[u][v] = ch-‘a‘+1;
    }
    rep(i,1,n)
    {
        int mx1=-1;
        rep(j,1,n) mx1=max(mx1, G[i][j]);
        mx[i] = mx1;
    }
    rep(i,1,n)
    {
        rep(j,1,n)
            if(solve(i, j, 0)) putchar(‘A‘);
            else putchar(‘B‘);
        puts("");
    }

    return 0;
}

原文地址:https://www.cnblogs.com/sbfhy/p/8394886.html

时间: 2024-07-28 15:01:27

Codeforces Round #459 (Div. 2) C 思维,贪心 D 记忆化dp的相关文章

Codeforces Round #224 (Div. 2) D 暴力搜索加记忆化

题意读了半年,英语太渣,题意是摆两个棋子在棋盘上作为起点,但是起点不能在#上,然后按照图的指示开始走, < 左 > 右 ^上 v下,走的时候只能按照图的指示走,如果前方是 #的话,可以走进去,但是 走进去之后便不能再走了,走的途中两个棋子不能相碰,但是最终都走到同一个#里是没事的,并且若是能走 无限步的话 输出 -1, 例如  > < 这样左右左右的走就能无限走,然后问你 两个棋子走的最大步数的和 一开始被输出-1给困住了,因为除了 .> <这样以外  还可以刚好形成一

Codeforces Round #423 (Div. 2) C 思维,并查集 或 线段树 D 树构造,水

Codeforces Round #423 (Div. 2, rated, based on VK Cup Finals) C. String Reconstruction   思维,并查集 或 线段树 题意:一个字符串被删除了,但给出 n条信息,要还原出可能的字典序最小的字符串.信息有:字符串ti,ki个位置xi,表明原本的字符串在xi位置是以字符串ti开头的. tags:惨遭 fst,一开始把所有字符串都存下来,排序做的,结果爆内存了.. 方法1: 考虑并查集,对于字符串 ti,在位置xi,

Codeforces Round #426 (Div. 2) D. The Bakery(线段树维护dp)

题目链接: Codeforces Round #426 (Div. 2) D. The Bakery 题意: 给你n个数,划分为k段,每段的价值为这一段不同的数的个数,问如何划分,使得价值最大. 题解: 考虑dp[i][j]表示划分为前j个数划分为i段的最大价值,那么这就是一个n*n*k的dp, 考虑转移方程dp[i][j]=max{dp[i][k]+val[k+1][j]},我们用线段树去维护这个max,线段树上每个节点维护的值是dp[i][k]+val[k+1][j],对于每加进来的一个数a

Codeforces Round #459 (Div. 2)题解

补题 codeforces 918C 题意 给定一个含有通配符?和()的字符串,问有多少子串是括号匹配的 解题思路 首先考虑不用栈求括号匹配的方法: bool solve(char* s) { int top=0; for (int i=0;i<strlen(s);i++) { if(s[i]=='(') top++; else top--; if(top<0) return false; } return top==0; } 由于在使用栈的括号匹配算法中,栈内是不存在)的,所以不难证明这个算

Codeforces Round #276 (Div. 1) A. Bits 贪心

A. Bits Let's denote as  the number of bits set ('1' bits) in the binary representation of the non-negative integer x. You are given multiple queries consisting of pairs of integers l and r. For each query, find the x, such that l ≤ x ≤ r, and is max

Codeforces Round #143 (Div. 2) (ABCD 思维场)

题目连链接:http://codeforces.com/contest/231 A. Team time limit per test:2 seconds memory limit per test:256 megabytes One day three best friends Petya, Vasya and Tonya decided to form a team and take part in programming contests. Participants are usually

Codeforces Round #459 (Div. 2)The Monster[匹配问题]

题意 给一个序列,包含(,),?,?可以被当做(或者),问你这个序列有多少合法的子序列. 分析 n^2枚举每一个子序列,暂时将每个?都当做右括号,在枚举右端点的时候同时记录两个信息:当前左括号多余多少个(top),已经将多少个?变成了右括号(cnt). 如果当前是(,top++. 如果当前是),top--. 如果当前是?,top--,cnt++; 如果top<0,我们需要判断一下当前还有没有之前被当做右括号的?,如果有的话,我们将其变为左括号,如果没有的话,意味着可以跳出循环了,之后都不会再合法

题解——Codeforces Round #508 (Div. 2) T3 (贪心)

贪心的选取最优解 然后相减好 记得要开long long #include <cstdio> #include <algorithm> #include <cstring> #include <set> #include <queue> #define int long long using namespace std; int ansa=0,ansb=0,posa=1,posb=1,n,a[1000100],b[1000100]; bool c

Codeforces Round #552 (Div. 3)-D-Walking Robot-(贪心)

http://codeforces.com/contest/1154/problem/D 解题: 1.无光的时候优先使用太阳能电池. 2.有光的时候 (1)太阳能电池没满电,让它充,使用普通电池 (2)太阳能电池满电,使用太阳能电池 #include<stdio.h> #include<math.h> #include<string.h> #include<algorithm> #include<string> #include<vecto