7.10洛谷多校4补
我在场上居然没过题,真是坑。
A
求树上两条从根出发的路径的并的点权异或和最大值。
n<=10^5
题解:
启发式合并+trie
代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 const int N = 100233; 5 int n, a[N], fa[N], son[N], size[N]; 6 vector<int> G[N]; 7 8 void dfs1(int x, int pre) { 9 fa[x] = pre; 10 size[x] = 1; 11 son[x] = 0; 12 for (auto y : G[x]) if (y != fa[x]) { 13 dfs1(y, x); 14 size[x] += size[y]; 15 if (!son[x] || size[son[x]] < size[y]) { 16 son[x] = y; 17 } 18 } 19 } 20 21 int pc = 1, ch[N * 40][2]; 22 void clear() { 23 pc = 1; 24 ch[1][0] = ch[1][1] = 0; 25 } 26 void insert(int x) { 27 int cur = 1; 28 for (int i = 29; ~i; i--) { 29 if (!ch[cur][x >> i & 1]) { 30 ch[cur][x >> i & 1] = ++pc; 31 ch[pc][0] = ch[pc][1] = 0; 32 } 33 cur = ch[cur][x >> i & 1]; 34 } 35 } 36 int ask(int x) { 37 if (pc == 1) return x; 38 int ans = 0, cur = 1; 39 for (int i = 29; ~i; i--) { 40 if (ch[cur][!(x >> i & 1)]) { 41 ans |= 1 << i; 42 cur = ch[cur][!(x >> i & 1)]; 43 } else { 44 cur = ch[cur][x >> i & 1]; 45 } 46 } 47 return ans; 48 } 49 50 int answer = 0; 51 52 void dfs3(int x, int cur) { 53 answer = max(answer, ask(cur)); 54 for (auto y : G[x]) if (y != fa[x]) { 55 dfs3(y, cur ^ a[y]); 56 } 57 } 58 void dfs4(int x, int cur) { 59 insert(cur); 60 for (auto y : G[x]) if (y != fa[x]) { 61 dfs4(y, cur ^ a[y]); 62 } 63 } 64 65 void dfs2(int x, int cur, bool keep) { 66 answer = max(answer, cur); 67 for (auto y : G[x]) if (y != fa[x] && y != son[x]) { 68 dfs2(y, cur ^ a[y], false); 69 } 70 if (son[x]) { 71 dfs2(son[x], cur ^ a[son[x]], true); 72 } else { 73 clear(); 74 } 75 for (auto y : G[x]) if (y != fa[x] && y != son[x]) { 76 dfs3(y, a[y]); 77 dfs4(y, cur ^ a[y]); 78 } 79 if (keep) { 80 insert(cur); 81 } else { 82 clear(); 83 } 84 } 85 86 int main() { 87 scanf("%d", &n); 88 for (int i = 1; i <= n; i++) { 89 scanf("%d", &a[i]); 90 } 91 for (int i = 1, x, y; i < n; i++) { 92 scanf("%d%d", &x, &y); 93 G[x].push_back(y); 94 G[y].push_back(x); 95 } 96 dfs1(1, 0); 97 dfs2(1, a[1], false); 98 printf("%d\n", answer); 99 }
B
网格上有一些颜色,每次删除一种颜色,若某种颜色不与其他任何还留在网格上的颜色相邻,这种颜色也会消失,问期望多少次删除能使所有颜色消失。
n,m<=1000 颜色数C<=10^6
题解:
把颜色看成点建图,有相邻则连边一条。
问题变成了,删除一个点,与该点相连的边都会消失,新生成的孤立点也消失,问期望删除点数。
一个点只有被直接删除了才会产生1的贡献,因其他点的删除而消失不会对答案产生贡献,因此需要计算一个点被删除的概率。
一个点被删除的概率=1-不被删除的概率。
一个点不被删除,只有它身边的所有点都被删除了,且自己没被删除,这个概率=d[x]/(d[x]+1) * (d[x]-1)/d[x] * ......*1/2=1/(d[x]+1),d[x]为x的度数。
所以答案为C-∑1/(d[x]+1)
代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int maxn=1e6+10,mod=1e9+7; 4 int n,m,C,a[1010][1010]; 5 set<int> st[maxn]; 6 int qpow(int a,int b){ 7 int ans=1; 8 for(;b;b>>=1,a=1ll*a*a%mod) 9 if(b&1)ans=1ll*ans*a%mod; 10 return ans; 11 } 12 int main(){ 13 scanf("%d%d%d",&n,&m,&C); 14 int mn=1e9,mx=-1e9; 15 for(int i=1;i<=n;++i) 16 for(int j=1;j<=m;++j) 17 scanf("%d",&a[i][j]),mn=min(mn,a[i][j]),mx=max(mx,a[i][j]); 18 for(int i=1;i<=C;++i)st[i].insert(i); 19 for(int i=1;i<=n;++i) 20 for(int j=1;j<=m;++j){ 21 if(i>1)st[a[i][j]].insert(a[i-1][j]); 22 if(i<n)st[a[i][j]].insert(a[i+1][j]); 23 if(j>1)st[a[i][j]].insert(a[i][j-1]); 24 if(j<m)st[a[i][j]].insert(a[i][j+1]); 25 } 26 int ans=0; 27 for(int i=1;i<=C;++i)ans=(ans+qpow(st[i].size(),mod-2))%mod; 28 if(mn==mx)printf("1\n"); 29 else printf("%d\n",(C-ans+mod)%mod); 30 }