7.24 校内模拟赛

题目链接:【已去世】

T1 送你一个DAG

题目描述:给定一个DAG,求所有$1$到$i$的路径的长度的$k$次方之和$mathrm{mod} 998244353$.

数据范围:$nleq 10^5,mleq 2*10^5,kleq 500$

使用第二类斯特林数的通常幂转下降幂,可以转化为对于$i$求$sum inom{l}{j}$,其中$0leq jleq k$,使用组合数的递推公式$inom{n}{m}=inom{n-1}{m}+inom{n-1}{m-1}$可以dp计算。

时间复杂度$O(mk)$。

 1 #include<bits/stdc++.h>
 2 #define Rint register int
 3 using namespace std;
 4 typedef long long LL;
 5 const int N = 100003, M = 200003, K = 503, mod = 998244353;
 6 int n, m, k, dp[N][K], fac[N], head[N], to[M], nxt[M], S[K][K];
 7 inline void add(int a, int b){
 8     static int cnt = 0;
 9     to[++ cnt] = b; nxt[cnt] = head[a]; head[a] = cnt;
10 }
11 inline void upd(int &a, int b){a += b; if(a >= mod) a -= mod;}
12 int que[N], front, rear, d[N];
13 int main(){
14     scanf("%d%d%d", &n, &m, &k);
15     for(Rint i = 1;i <= m;i ++){
16         int u, v;
17         scanf("%d%d", &u, &v);
18         add(u, v); ++ d[v];
19     }
20     S[0][0] = 1;
21     for(Rint i = 1;i <= k;i ++)
22         for(Rint j = 1;j <= i;j ++)
23             S[i][j] = (S[i - 1][j - 1] + 1ll * j * S[i - 1][j]) % mod;
24     fac[0] = 1;
25     for(Rint i = 1;i <= k;i ++) fac[i] = 1ll * fac[i - 1] * i % mod;
26     front = rear = 1;
27     for(Rint i = 1;i <= n;i ++)
28         if(!d[i]) que[rear ++] = i, dp[i][0] = 1;
29     while(front < rear){
30         int now = que[front ++];
31         for(Rint i = head[now];i;i = nxt[i]){
32             -- d[to[i]];
33             if(!d[to[i]]) que[rear ++] = to[i];
34             upd(dp[to[i]][0], dp[now][0]);
35             for(Rint j = 1;j <= k;j ++){
36                 upd(dp[to[i]][j], dp[now][j]);
37                 upd(dp[to[i]][j], dp[now][j - 1]);
38             }
39         }
40     }
41     for(Rint i = 1;i <= n;i ++){
42         int ans = 0;
43         for(Rint j = 0;j <= k;j ++) upd(ans, 1ll * fac[j] * S[k][j] % mod * dp[i][j] % mod);
44         printf("%d
", ans);
45     }
46 }
T1

 1 #include<bits/stdc++.h>
 2 #define Rint register int
 3 using namespace std;
 4 typedef long long LL;
 5 const int N = 100003, M = 200003, K = 503, mod = 998244353;
 6 int n, m, k, dp[N][K], fac[N], head[N], to[M], nxt[M], S[K][K];
 7 inline void add(int a, int b){
 8     static int cnt = 0;
 9     to[++ cnt] = b; nxt[cnt] = head[a]; head[a] = cnt;
10 }
11 inline void upd(int &a, int b){a += b; if(a >= mod) a -= mod;}
12 int que[N], front, rear, d[N];
13 int main(){
14     scanf("%d%d%d", &n, &m, &k);
15     for(Rint i = 1;i <= m;i ++){
16         int u, v;
17         scanf("%d%d", &u, &v);
18         add(u, v); ++ d[v];
19     }
20     S[0][0] = 1;
21     for(Rint i = 1;i <= k;i ++)
22         for(Rint j = 1;j <= i;j ++)
23             S[i][j] = (S[i - 1][j - 1] + 1ll * j * S[i - 1][j]) % mod;
24     fac[0] = 1;
25     for(Rint i = 1;i <= k;i ++) fac[i] = 1ll * fac[i - 1] * i % mod;
26     front = rear = 1;
27     for(Rint i = 1;i <= n;i ++)
28         if(!d[i]) que[rear ++] = i, dp[i][0] = 1;
29     while(front < rear){
30         int now = que[front ++];
31         for(Rint i = head[now];i;i = nxt[i]){
32             -- d[to[i]];
33             if(!d[to[i]]) que[rear ++] = to[i];
34             upd(dp[to[i]][0], dp[now][0]);
35             for(Rint j = 1;j <= k;j ++){
36                 upd(dp[to[i]][j], dp[now][j]);
37                 upd(dp[to[i]][j], dp[now][j - 1]);
38             }
39         }
40     }
41     for(Rint i = 1;i <= n;i ++){
42         int ans = 0;
43         for(Rint j = 0;j <= k;j ++) upd(ans, 1ll * fac[j] * S[k][j] % mod * dp[i][j] % mod);
44         printf("%d
", ans);
45     }
46 }T1

T2 送你一棵圣诞树

题目描述:给定一棵点带色的树,支持修改单点颜色,查询子树颜色在$[l,r]$中的数量(相同的只算一个),强制在线。

数据范围:$n,c_ileq 10^5$。

如果直接转化为在序列上做的话是一个四维偏序,时间复杂度高而且还有可能爆空间。

所以有一个套路,对于每一种颜色的点,按照dfs序排序,将每个点打上+1,将每相邻两个点的lca打上-1,这样就可以做到相同的只算一个了。

这里是注意到了子树相对于序列的区间多了一个条件,那就是询问的序列只有相离和包含关系,这样就可以去掉一维了。

使用set维护每种颜色的点,用树状数组套动态开点线段树就可以在线做三维偏序了。

hsz神仙说即使不知道这个技巧也可以使用$O(n^{frac{5}{3}})$的分块轻松跑过去(但是对于我来说就太难写了,膜膜膜)。

  1 #include<bits/stdc++.h>
  2 #define Rint register int
  3 using namespace std;
  4 const int N = 100003;
  5 int n, q, t, col[N], head[N], to[N << 1], nxt[N << 1], lastans;
  6 inline void add(int a, int b){
  7     static int cnt = 0;
  8     to[++ cnt] = b; nxt[cnt] = head[a]; head[a] = cnt;
  9 }
 10 int fa[N], wson[N], dep[N], siz[N];
 11 inline void dfs1(int x){
 12     siz[x] = 1;
 13     for(Rint i = head[x];i;i = nxt[i])
 14         if(to[i] != fa[x]){
 15             dep[to[i]] = dep[x] + 1;
 16             fa[to[i]] = x;
 17             dfs1(to[i]);
 18             siz[x] += siz[to[i]];
 19             if(siz[to[i]] > siz[wson[x]]) wson[x] = to[i];
 20         }
 21 }
 22 int dfn[N], pre[N], top[N], tim;
 23 inline void dfs2(int x, int topf){
 24     dfn[x] = ++ tim; pre[tim] = x; top[x] = topf;
 25     if(wson[x]) dfs2(wson[x], topf);
 26     for(Rint i = head[x];i;i = nxt[i])
 27         if(to[i] != fa[x] && to[i] != wson[x])
 28             dfs2(to[i], to[i]);
 29 }
 30 struct cmp {inline bool operator () (int a, int b){return dfn[a] < dfn[b];}};
 31 set<int, cmp> vec[N];
 32 inline int LCA(int u, int v){
 33     while(top[u] != top[v]){
 34         if(dep[top[u]] < dep[top[v]]) swap(u, v);
 35         u = fa[top[u]];
 36     }
 37     return dep[u] < dep[v] ? u : v;
 38 }
 39 int root[N], seg[N * 150], ls[N * 150], rs[N * 150], cnt;
 40 inline void change(int &x, int L, int R, int pos, int val){
 41     if(!x) x = ++ cnt; seg[x] += val;
 42     if(L == R) return;
 43     int mid = L + R >> 1;
 44     if(pos <= mid) change(ls[x], L, mid, pos, val);
 45     else change(rs[x], mid + 1, R, pos, val);
 46 }
 47 inline int query(int &x, int L, int R, int l, int r){
 48     if(!x || r < l) return 0;
 49     if(l <= L && R <= r) return seg[x];
 50     int mid = L + R >> 1, res = 0;
 51     if(l <= mid) res = query(ls[x], L, mid, l, r);
 52     if(mid < r) res += query(rs[x], mid + 1, R, l, r);
 53     return res;
 54 }
 55 inline int lowbit(int x){return x & -x;}
 56 inline void change(int posx, int posy, int val){
 57     while(posx <= n){
 58         change(root[posx], 1, n, posy, val);
 59         posx += lowbit(posx);
 60     }
 61 }
 62 inline int query(int posx, int l, int r){
 63     int res = 0;
 64     while(posx){
 65         res += query(root[posx], 1, n, l, r);
 66         posx -= lowbit(posx); 
 67     }
 68     return res;
 69 }
 70 int main(){
 71     scanf("%d%d%d", &n, &q, &t);
 72     for(Rint i = 1;i <= n;i ++)
 73         scanf("%d", col + i);
 74     for(Rint i = 1;i < n;i ++){
 75         int a, b;
 76         scanf("%d%d", &a, &b);
 77         add(a, b); add(b, a);
 78     }
 79     dfs1(1); dfs2(1, 1);
 80     for(Rint i = 1;i <= n;i ++) vec[col[i]].insert(i);
 81     for(Rint i = 1;i <= n;i ++)
 82         for(set<int, cmp> :: iterator it = vec[i].begin();it != vec[i].end();it ++){
 83             change(i, dfn[*it], 1);
 84             if(next(it) != vec[i].end()) change(i, dfn[LCA(*it, *next(it))], -1);
 85         }
 86     while(q --){
 87         int opt, u, x, y;
 88         scanf("%d%d%d", &opt, &u, &x);
 89         if(t) u ^= lastans, x ^= lastans;
 90         if(opt == 1){
 91             scanf("%d", &y); if(t) y ^= lastans;
 92             printf("%d
", lastans = query(y, dfn[u], dfn[u] + siz[u] - 1) - query(x - 1, dfn[u], dfn[u] + siz[u] - 1));
 93         } else {
 94             set<int, cmp> :: iterator it = vec[col[u]].find(u);
 95             change(col[u], dfn[u], -1);
 96             if(it != vec[col[u]].begin()) change(col[u], dfn[LCA(*it, *prev(it))], 1);
 97             if(next(it) != vec[col[u]].end()) change(col[u], dfn[LCA(*it, *next(it))], 1);
 98             if(it != vec[col[u]].begin() && next(it) != vec[col[u]].end())
 99                 change(col[u], dfn[LCA(*prev(it), *next(it))], -1);
100             vec[col[u]].erase(it); col[u] = x;
101             it = vec[x].insert(u).first;
102             if(it != vec[x].begin()) change(x, dfn[LCA(*prev(it), *it)], -1);
103             if(next(it) != vec[x].end()) change(x, dfn[LCA(*it, *next(it))], -1);
104             if(it != vec[x].begin() && next(it) != vec[x].end())
105                 change(x, dfn[LCA(*prev(it), *next(it))], 1);
106             change(x, dfn[u], 1);
107         }
108     }
109 }
T2

T3 送你一棵圣诞树

神仙题,咕咕咕。。。

原文地址:https://www.cnblogs.com/AThousandMoons/p/11249711.html