牛客练习赛97
比赛链接
牛客练习赛97
C.哦~唔西迪西小姐~
题目描述
唔西迪西地在正处在一个冰火迷宫中,迷宫由 \(n\) 个格子组成,每个格子要么是冰之格,要么是火之格,唔西迪西网 开始可以选择从迷宫中任意一个扞始走,走到第 \(i\) 个立置时会得到值为 \(a_{i}\) 的积分。(注意:唔西迪西也可以选择一 个格子都不走)
如果唔西迪西当前在㲻之格,那么她可以选择一个编号大于当前格子的冰之格,跳到氻里。如果唔西迪西当前在火之 格,那么她可以选择一个编号大于当前格子的火之格,跳到氻哩。如果唔西迪西目前没有格子可以走,那么结束。同 时,即使存在可以跳过去的格子,唔西迪西也可以选择在任意时刻结束。
\(\mathrm{~ 唔 西 迪 西 想 最 大 化 她 的 得 分 , 于 是 她 学 厺 了 一 个 超 能 力 , 她 能 在 比 赛 开 始 的 时 候 改 变 最 ~}\) 个格子从冰之格变成火之格或从火之格变成冰之格,改变第 \(i\) 个格子的状态会让唔西迪西的得分減少 \(p_{i}\) 。 (唔西迪 西改变格子的状态后才开始挑选起点开始行动,也就是说,得分分成两部分,一部分是改变格子状态的得分, 部分 是走格子的得分)
你能告诉唔西迪西她最多得几分吗
输入描述:
第一行两个正整数 \(n, m\left(1 \leq n, m \leq 10^{5}\right)\) 。
第二行 \(n\) 个整数表示 \(a_{i}\) 。
第三行 \(n\) 个整数表示 \(p_{i}\left(-10^{5} \leq a_{i}, p_{i} \leq 10^{5}\right)\) 。
第四行 \(n\) 个整数 \(b_{i}\) 为 0 或 1,0 表示这个格子是冰之格, 1 表示这个格子是火之格。
输出描述:
一个数表示答案。
示例1
输入
3 2
1 15 9
2 5 7
1 0 1
输出
20
示例2
输入
10 3
80 86 57 69 59 52 94 74 9 63
8 32 77 64 53 49 22 68 27 63
1 0 0 0 1 0 0 1 1 1
输出
442
解题思路
贪心
考虑冰之格的情况,火之格同理,不妨考虑不能改变格子状态的情况,即每个冰之格正数之和即为答案,当有状态改变的情况时,考虑对答案的影响,当改变冰之格时,如果 \(a[i]>0\),对答案的影响为 \(-p[i]-a[i]\),否则影响为 \(-p[i]\),当改变火之格时,如果 \(a[i]>0\)时,对答案的影响为 \(a[i]-p[i]\),否则影响为 \(-p[i]\)
- 时间复杂度:\(O(nlogn)\)
代码
// Problem: 哦~唔西迪西小姐~
// Contest: NowCoder
// URL: https://ac.nowcoder.com/acm/contest/11187/C
// Memory Limit: 524288 MB
// Time Limit: 2000 ms
//
// Powered by CP Editor (https://cpeditor.org)
// %%%Skyqwq
#include <bits/stdc++.h>
// #define int long long
#define help {cin.tie(NULL); cout.tie(NULL);}
#define pb push_back
#define fi first
#define se second
#define mkp make_pair
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; }
template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; }
template <typename T> void inline read(T &x) {
int f = 1; x = 0; char s = getchar();
while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); }
while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar();
x *= f;
}
const int N=1e5+5;
int n,m,a[N],p[N];
vector<PII> v1,v2;
vector<int> v;
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)cin>>a[i];
for(int i=1;i<=n;i++)cin>>p[i];
for(int i=1;i<=n;i++)
{
int x;
cin>>x;
if(x==0)v1.pb({a[i],i});
else
v2.pb({a[i],i});
}
LL res1=0;
for(int i=0;i<v1.size();i++)res1+=max(0,v1[i].fi);
for(int i=0;i<v1.size();i++)
if(v1[i].fi<=0)v.pb(-p[v1[i].se]);
else
v.pb(-p[v1[i].se]-v1[i].fi);
for(int i=0;i<v2.size();i++)
if(v2[i].fi>0)v.pb(v2[i].fi-p[v2[i].se]);
else
v.pb(-p[v2[i].se]);
// v.pb(max(0,);
sort(v.begin(),v.end());
for(int i=v.size()-1;i>=0&&v.size()-1-i+1<=m;i--)res1+=max(0,v[i]);
v.clear();
LL res2=0;
for(int i=0;i<v2.size();i++)res2+=max(0,v2[i].fi);
for(int i=0;i<v2.size();i++)
if(v2[i].fi<=0)v.pb(-p[v2[i].se]);
else
v.pb(-p[v2[i].se]-v2[i].fi);
for(int i=0;i<v1.size();i++)
if(v1[i].fi>0)v.pb(v1[i].fi-p[v1[i].se]);
else
v.pb(-p[v1[i].se]);
sort(v.begin(),v.end());
for(int i=v.size()-1;i>=0&&v.size()-1-i+1<=m;i--)res2+=max(0,v[i]);
cout<<max(res1,res2);
return 0;
}
月之暗面
题目描述
给出一棵 \(n\) 个点的树,有 \(x\) 种普通颜色,\(y\) 种特殊颜色
现在要给树上的每个节点染色,普通颜色染色没有限制,但两个相邻的节点不能染相同颜色的特殊颜色
求染色方案数,答案对 \(998244353\) 取模。
输入描述:
第一行三个整数 \(n, x, y ( 1 \leq n \leq 10^{6}, 1 \leq x, y \leq 10^{9} )\), 分别表示树的节点数, 普通颜色的种数, 特殊 颜色的种数
接下来 \(n-1\) 行描述这棵树, 每行两个整数 \(u, v(1 \leq u, v, \leq n)\) 表示从 \(u\) 到 \(v\) 有一条树边 保证输入的树合法。
输出描述:
一行一个整数,表示答案。
示例1
输入
2 1 2
1 2
输出
7
示例2
输入
5 3 3
1 2
1 3
3 4
3 5
输出
5664
示例3
输入
11 45 14
6 5
6 7
7 9
7 8
9 2
8 10
2 1
8 3
10 4
4 11
输出
188688550
解题思路
树形dp
- 状态表示:
-
- \(f[u][0]\) 表示 \(u\) 染色为普通颜色时其及其子树的方案数
-
- \(f[u][1]\) 表示 \(u\) 染色为特殊颜色时其及其子树的方案数
- 状态计算:
-
- \(f[u][0]=\prod (f[v][0]+f[v][1])\),其中 \(v\) 为 \(u\) 的儿子节点
-
- \(f[u][1]=\prod (f[v][0]+f[v][1]-f[v][1]/y)\)
注意:不能出现相邻的特殊颜色,所以计算某个根节点特殊颜色的方案数时需要减去儿子特殊颜色等于父节点的情况
- 时间复杂度:\(O(n)\)
代码
// Problem: 月之暗面
// Contest: NowCoder
// URL: https://ac.nowcoder.com/acm/contest/11187/D
// Memory Limit: 524288 MB
// Time Limit: 4000 ms
//
// Powered by CP Editor (https://cpeditor.org)
// %%%Skyqwq
#include <bits/stdc++.h>
#define int long long
#define help {cin.tie(NULL); cout.tie(NULL);}
#define pb push_back
#define fi first
#define se second
#define mkp make_pair
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; }
template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; }
template <typename T> void inline read(T &x) {
int f = 1; x = 0; char s = getchar();
while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); }
while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar();
x *= f;
}
const int N=1e6+5,mod=998244353;
int f[N][2],n,x,y;
vector<int> adj[N];
bool vis[N];
int ksm(int a,int b,int p)
{
int res=1%p;
for(;b;b>>=1)
{
if(b&1)res=res*a%p;
a=a*a%p;
}
return res;
}
PII dfs(int u)
{
int res1=x,res2=y;
for(int v:adj[u])
{
auto t=dfs(v);
int t1=t.fi,t2=t.se;
res1=res1*(t1+t2)%mod;
res2=(res2*(t1+t2-t2*ksm(y,mod-2,mod)%mod)%mod+mod)%mod;
}
return {res1,res2};
}
signed main()
{
cin>>n>>x>>y;
for(int i=1;i<n;i++)
{
int u,v;
cin>>u>>v;
adj[u].pb(v);
vis[v]=true;
}
int root=1;
while(vis[root])root++;
cout<<(dfs(root).fi+dfs(root).se)%mod;
return 0;
}