steambird @ 2024-04-27 21:37:08
大致思路:先倒着扫一遍确定乘法,再正着扫一遍
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <vector>
#include <queue>
using namespace std;
inline void train() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
}
constexpr int N = 1e5 + 4, Q = 1e6 + 3;
constexpr long long MODER = 998244353;
long long origin[N], timing[N], op_timing[N], op_adding[N], counter[N], adding[N];
long long modifiers[N];
long long final_timing = 1ll;
vector<int> active[N], passive[N];
int active_ins[N], passive_ins[N];
long long op_adding_at[N];
short node_type[N];
long long g_timestamp = 0;
struct order {
int to, depth;
long long timestamp;
order(int to = 0, int depth = 0, long long alignment = -1) : to(to), depth(depth),
timestamp(g_timestamp + alignment) {
if (alignment < 0) {
timestamp -= alignment;
g_timestamp++;
}
}
};
bool operator > (const order &a, const order &b) {
if (a.depth == b.depth) return a.timestamp > b.timestamp;
return a.depth < b.depth;
}
long long fastpow(long long a, long long b) {
if (b <= 0) return 1ll;
else if (b & 1) return a * fastpow(a, b - 1) % MODER;
else {
long long s = fastpow(a, b >> 1);
return s * s % MODER;
}
}
priority_queue<order, vector<order>, greater<order> > pq;
int n, m, q;
signed main() {
train();
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> origin[i];
}
cin >> m;
for (int i = 1; i <= m; i++) {
int ns;
timing[i] = 1ll;
cin >> node_type[i];
switch (node_type[i]) {
case 1:
cin >> op_adding_at[i] >> op_adding[i];
break;
case 2:
cin >> op_timing[i];
timing[i] = op_timing[i];
break;
case 3:
cin >> ns;
for (int j = 0; j < ns; j++) {
int x;
cin >> x;
active[i].push_back(x);
active_ins[x]++;
passive[x].push_back(i);
passive_ins[i]++;
}
break;
}
}
cin >> q;
m++;
timing[m] = 1ll;
node_type[m] = 3;
counter[m] = 1;
adding[m] = 1ll;
for (int i = 0; i < q; i++) {
int x;
cin >> x;
active[m].push_back(x);
active_ins[x]++;
passive[x].push_back(m);
passive_ins[m]++;
}
for (int i = 1; i <= m; i++) {
if (passive_ins[i] == 0) pq.push(order(i));
}
for (int i = 0; i < m; i++) {
order pf = pq.top();
pq.pop();
for (auto &j : passive[pf.to]) {
timing[j] = (timing[j] * timing[pf.to]) % MODER;
passive_ins[j]--;
if (passive_ins[j] == 0) {
pq.push(order(j, pf.depth + 1));
}
}
}
while (!pq.empty()) {
pq.pop();
}
for (int i = 1; i <= m; i++) {
if (active_ins[i] == 0) pq.push(order(i));
}
for (int i = 0; i < m; i++) {
order pf = pq.top();
pq.pop();
switch (node_type[pf.to]) {
case 1:
modifiers[op_adding_at[pf.to]] = (modifiers[op_adding_at[pf.to]] + (adding[pf.to] * op_adding[pf.to] % MODER)) % MODER;
break;
case 2:
final_timing = (final_timing * fastpow(timing[pf.to], counter[pf.to] % (MODER-1))) % MODER;
break;
case 3:
long long accu = 1ll;
for (int jr = active[pf.to].size() - 1; jr >= 0; jr--) {
auto &j = active[pf.to][jr];
counter[j] += counter[pf.to];
active_ins[j]--;
adding[j] = (adding[j] + (adding[pf.to] * accu) % MODER) % MODER;
if (active_ins[j] == 0) {
pq.push(order(j, pf.depth + 1, jr));
}
accu = (accu * timing[j]) % MODER;
}
g_timestamp += active[pf.to].size() + 1;
break;
}
}
for (int i = 1; i <= n; i++) {
long long timed = (origin[i] * final_timing) % MODER;
long long added = (timed + modifiers[i]) % MODER;
cout << added << ' ';
}
cout << endl;
return 0;
}
by steambird @ 2024-04-28 18:34:58
解决:指数要取模(而且根据费马小是模