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 ", 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; }