I题nico和niconiconi
很明显的dp,dp[i]表示前i个字符的最大值。输出dp[n]即可。
#include<bits/stdc++.h>
//#pragma GCC optimize(2)
#include<iostream>
#include<stdio.h>
#include<string>
#include<cstring>
#include<set>
#include<map>
#include<stack>
#include<queue>
#include<algorithm>
#define ll long long
#define lowbit(x) (x)&(-x)
using namespace std;
template<class T>
void read(T& x)
{
T res = 0, f = 1;
char c = getchar();
while (!isdigit(c))
{
if (c == '-')f = -1; c = getchar();
}
while (isdigit(c))
{
res = (res << 3) + (res << 1) + c - '0'; c = getchar();
}
x = res * f;
}
const ll N = 300000 + 20;
ll dp[N], n, a, b, c;
string s;
//1.是不是爆了int
int main()
{
//ios::sync_with_stdio(false);
#ifndef ONLINE_JUDGE
freopen("182.txt", "r", stdin);
#endif // ONLINE_JUDGE
read(n), read(a), read(b), read(c);
cin >> s;
for (int i = 0; i < s.size(); i++)
{
dp[i] = max(dp[max(i - 1,0)], dp[i]);
string p1 = s.substr(i, 4);
string p2 = s.substr(i, 6);
string p3 = s.substr(i, 10);
if (p1 == "nico")dp[i+3] = max(dp[i+3], dp[i] + a);
if (p2== "niconi")dp[i+5] = max(dp[i+5], dp[i] + b);
if (p3 == "niconiconi")dp[i+9] = max(dp[i+9], dp[i] + c);
}
printf("%lld", dp[n - 1]);
return 0;
}
F题maki和tree
路径只有一个黑点的情况有两种,一种是黑点端点,一种是两边端点都是白色中间有一个黑点。所以我们预处理出所有白点连通块中白点个数。对每一个黑点求出符合的路径。
#include<bits/stdc++.h>
//#pragma GCC optimize(2)
#include<iostream>
#include<stdio.h>
#include<string>
#include<cstring>
#include<set>
#include<map>
#include<stack>
#include<queue>
#include<algorithm>
#define ll long long
#define lowbit(x) (x)&(-x)
using namespace std;
template<class T>
void read(T& x)
{
T res = 0, f = 1;
char c = getchar();
while (!isdigit(c))
{
if (c == '-')f = -1; c = getchar();
}
while (isdigit(c))
{
res = (res << 3) + (res << 1) + c - '0'; c = getchar();
}
x = res * f;
}
const ll N = 100000 + 10;
ll n, head[N], sumline, dfn[N], lown[N], tag[N], cot, tot, sum[N], ans=0;
char col[N];
bool vis[N];
struct line
{
int to, nxt;
}p[N*5];
void add(int a, int b)
{
sumline++;
p[sumline].nxt = head[a];
head[a] = sumline;
p[sumline].to = b;
}
stack<int>pls;
void tarjan(int u, int fa)
{
dfn[u] = lown[u] = ++tot;
vis[u] = 1;
pls.push(u);
for (int i = head[u]; i; i = p[i].nxt)
{
int to = p[i].to;
if (col[to] == 'B')continue;
if (!dfn[to])
{
tarjan(to, u);
lown[u] = min(lown[u], lown[to]);
}
else if (vis[to])
lown[u] = min(lown[u], dfn[to]);
}
if (lown[u] == dfn[u])
{
cot++;
while (pls.top() != u)
{
tag[pls.top()] = cot;
vis[pls.top()] = 0;
pls.pop();
sum[cot]++;
}
tag[pls.top()] = cot;
vis[pls.top()] = 0;
pls.pop();
sum[cot]++;
}
}
ll getans(vector<int>qls)
{
ll sans = 0;
ll sn = qls.size();
ll tot = 0;
for (int i = 0; i < sn; i++)
tot+=qls[i];
for (int i = 0; i < sn; i++)
{
sans += (tot - qls[i]) * qls[i];
}
sans /= 2;
return sans + tot;
}
//1.是不是爆了int
int main()
{
//ios::sync_with_stdio(false);
#ifndef ONLINE_JUDGE
freopen("182.txt", "r", stdin);
#endif // ONLINE_JUDGE
read(n);
scanf("%s", col + 1);
for (int i = 1; i <= n - 1; i++)
{
int x, y;
read(x), read(y);
add(x, y);
add(y, x);
}
for (int i = 1; i <= n; i++)
{
if (col[i] == 'W' && !dfn[i])
tarjan(i, -1);
}
for (int i = 1; i <= n; i++)
{
if (col[i] == 'B')
{
vector<int>js;
for (int j = head[i]; j; j = p[j].nxt)
{
if(col[p[j].to]=='W')
js.push_back(sum[tag[p[j].to]]);
}
ans += getans(js);
}
}
printf("%lld", ans);
return 0;
}