正睿20NOIp前冲刺day3
估分:10+7+0=17
实际:0+0+0=0
T1:
没初始化,丢了暴力10分
hash,每个点存储从1号点到他的路径上的点的hash值,用dfs序加树状数组来维护
1 #include<cstdio> 2 #include<cstring> 3 #include<time.h> 4 #include<vector> 5 #include<iostream> 6 #include<algorithm> 7 using namespace std; 8 9 #define pb push_back 10 #define lowbit(x) x&-x 11 12 typedef unsigned long long ULL; 13 14 const int N = 250010; 15 const int P = 998244353; 16 17 int n; 18 int dep[N], dfn[N], ed[N], fa[N][25], tim; 19 vector<int> e[N]; 20 ULL a[N], tr[N << 2]; 21 ULL vn[N], sum[N]; 22 23 void insert(int x, ULL c) 24 { 25 for (; x <= n; x += lowbit(x)) tr[x] ^= c; 26 } 27 28 ULL query(int x) 29 { 30 ULL res = 0; 31 for (; x; x -= lowbit(x)) res ^= tr[x]; 32 return res; 33 } 34 35 void dfs(int u, int pa) 36 { 37 dfn[u] = ++tim; 38 dep[u] = dep[pa] + 1; 39 fa[u][0] = pa; 40 for (int i = 1; i <= 20; i++) fa[u][i] = fa[fa[u][i - 1]][i - 1]; 41 for (int i = 0; i < e[u].size(); i++) 42 { 43 int j = e[u][i]; 44 if (j == pa) continue; 45 dfs(j, u); 46 } 47 ed[u] = tim; 48 } 49 50 int LCA(int x, int y) 51 { 52 if (dep[x] < dep[y]) swap(x, y); 53 for (int i = 20; ~i; i--) 54 { 55 if (dep[fa[x][i]] >= dep[y]) x = fa[x][i]; 56 } 57 58 if (x == y) return x; 59 60 for (int i = 20; ~i; i--) 61 { 62 if (fa[x][i] != fa[y][i]) x = fa[x][i], y = fa[y][i]; 63 } 64 return fa[x][0]; 65 } 66 67 void init() 68 { 69 tim = 0; 70 memset(dep, 0, sizeof(dep)); 71 memset(fa, 0, sizeof(fa)); 72 memset(tr, 0, sizeof(tr)); 73 } 74 75 int main() 76 { 77 //freopen("input.txt", "r", stdin); 78 vn[0] = 1; 79 for (int i = 1; i <= 250000; i++) vn[i] = vn[i - 1] * P, sum[i] = sum[i - 1] ^ vn[i]; 80 81 int T; 82 scanf("%d", &T); 83 while (T--) 84 { 85 init(); 86 int q; 87 scanf("%d%d", &n, &q); 88 for (int i = 1; i <= n; i++) scanf("%llu", &a[i]), a[i] = vn[a[i]], e[i].clear(); 89 for (int i = 1; i < n; i++) 90 { 91 int x, y; 92 scanf("%d%d", &x, &y); 93 e[x].pb(y), e[y].pb(x); 94 } 95 96 dfs(1, 0); 97 for (int i = 1; i <= n; i++) insert(dfn[i], a[i]), insert(ed[i] + 1, a[i]); 98 99 while (q--) 100 { 101 int op, x, y; 102 scanf("%d%d%d", &op, &x, &y); 103 if (op == 1) 104 { 105 int z = LCA(x, y); 106 ULL num = query(dfn[x]) ^ query(dfn[y]) ^ a[z]; 107 if (num == sum[dep[x] + dep[y] - 2 * dep[z] + 1]) puts("Yes"); 108 else puts("No"); 109 } 110 else 111 { 112 ULL k = vn[y]; 113 insert(dfn[x], a[x] ^ k), insert(ed[x] + 1, a[x] ^ k); 114 a[x] = k; 115 } 116 } 117 } 118 }
T2:
数组开小+没开longlong,7分暴力没了
将图中的点分为4类,G(啥也不坐),B(单车),S(在车站),T(地铁)。
从 G->G,不需要连边。
从 G->B:每一个对应的点连一条长度为 的边。
从 B->G:每一个对应的点连一条长度为 的边。
从 B->B:按照题目给出的自行车路线图,连边 。
从G->S:每一个对应的点连一条长度为 的边。
从 S->G:不连边。 从 S->S:不需要连边。
从 S->T:每一个对应的点连一条长度为 的边。
从 T->S:每一个对应的点连一个长度为 cici 的边。
从 T->G:每一个对应的点连一条长度为 的边。
从 T->T:按照地铁线路图连边。
最后要加上等车时间,算进边权里就行,然后就直接跑dijkstra
1 #include<cstdio> 2 #include<cstring> 3 #include<queue> 4 #include<iostream> 5 #include<algorithm> 6 using namespace std; 7 8 typedef long long LL; 9 10 const int N = 4e6 + 7; 11 const LL INF = 1e18; 12 const int MOD = 998244353; 13 14 int n, m, r, s, k; 15 LL x; 16 int G[N], B[N], S[N], T[N]; 17 int v[N]; 18 LL l[N]; 19 int idx = 0; 20 int head[N], cnt; 21 LL dis[N], e[N], c[N]; 22 bool vis[N]; 23 24 struct Node 25 { 26 int id; 27 LL dist; 28 Node() {} 29 Node(int id, LL dist) :id(id), dist(dist) {} 30 bool operator < (const Node y) const 31 { 32 return dist > y.dist; 33 } 34 }; 35 36 struct Edge 37 { 38 int e, next; 39 LL w, t, mod; 40 }edge[N]; 41 42 void add(int s, int e, LL w, LL t, LL mod) 43 { 44 edge[++cnt].e = e; 45 edge[cnt].w = w; 46 edge[cnt].t = t; 47 edge[cnt].mod = mod; 48 edge[cnt].next = head[s]; 49 head[s] = cnt; 50 } 51 52 priority_queue<Node> q; 53 54 void Dijstra(int s) 55 { 56 memset(vis, 0, sizeof(vis)); 57 for (int i = 1; i <= idx; ++i) dis[i] = INF; 58 dis[s] = 0; 59 q.push(Node(s, 0)); 60 while (!q.empty()) 61 { 62 Node x = q.top(); 63 q.pop(); 64 65 int now = x.id; 66 if (vis[now]) continue; 67 vis[now] = 1; 68 for (int i = head[now]; i; i = edge[i].next) 69 { 70 int to = edge[i].e; 71 LL d = dis[now] + edge[i].w; 72 LL wait = 0; 73 if (edge[i].t) wait = (edge[i].mod - dis[now] % edge[i].t + edge[i].t) % edge[i].t; 74 if (dis[to] > d + wait) 75 { 76 dis[to] = d + wait; 77 q.push(Node(to, dis[to])); 78 } 79 } 80 } 81 } 82 83 int main() 84 { 85 scanf("%d%d%d%lld", &n, &r, &s, &x); 86 for (int i = 1; i <= n; ++i) scanf("%lld", &e[i]); 87 for (int i = 1; i <= n; ++i) scanf("%lld", &c[i]); 88 for (int i = 1; i <= n; ++i) G[i] = ++idx, B[i] = ++idx, S[i] = ++idx; 89 for (int i = 1; i <= n; ++i) add(G[i], B[i], x, 0, 0), add(B[i], G[i], 0, 0, 0); 90 for (int i = 1; i <= n; ++i) add(G[i], S[i], e[i], 0, 0); 91 for (int i = 1; i <= r; ++i) 92 { 93 int u, v; 94 LL w; 95 scanf("%d%d%lld", &u, &v, &w); 96 add(B[u], B[v], w, 0, 0); 97 add(B[v], B[u], w, 0, 0); 98 } 99 100 while (s--) 101 { 102 scanf("%d", &k); 103 for (int i = 1; i <= k; ++i) scanf("%d%lld", &v[i], &l[i]); 104 scanf("%d", &v[k + 1]); 105 106 LL t; 107 scanf("%lld", &t); 108 for (int i = 1; i <= k; ++i) T[v[i]] = ++idx; 109 if (v[k + 1] != v[1]) T[v[k + 1]] = ++idx; 110 111 LL mod = 0; 112 for (int i = 1; i <= k; ++i) 113 { 114 add(T[v[i]], T[v[i + 1]], l[i], t, mod); 115 mod = (mod + l[i]) % t; 116 } 117 118 if (v[k + 1] == v[1]) mod = 0; 119 for (int i = k; i >= 1; --i) 120 { 121 add(T[v[i + 1]], T[v[i]], l[i], t, mod); 122 mod = (mod + l[i]) % t; 123 } 124 for (int i = 1; i <= k; ++i) 125 { 126 add(S[v[i]], T[v[i]], 0, 0, 0); 127 add(T[v[i]], S[v[i]], c[v[i]], 0, 0); 128 add(T[v[i]], G[v[i]], e[v[i]], 0, 0); 129 } 130 131 if (v[k + 1] != v[1]) 132 { 133 add(S[v[k + 1]], T[v[k + 1]], 0, 0, 0); 134 add(T[v[k + 1]], S[v[k + 1]], c[v[k + 1]], 0, 0); 135 add(T[v[k + 1]], G[v[k + 1]], e[v[k + 1]], 0, 0); 136 } 137 } 138 Dijstra(G[1]); 139 for (int i = 1; i <= n; ++i) printf("%lld ", dis[G[i]]); 140 }
T3:
剪枝写错了,写成会炸int的了,10分暴力也没了
玄学,不会写
总结:
暴力容易写炸啊,之后还是要保证暴力绝对正确再写其他部分分。还有代码能力还是不行,第一题和第二题都想到正解的思路了,但不知道怎么写,第一题不知道hash函数怎么弄才好,第二题建图的代码没写完,第三题能得10分的剪枝想到了,但实现的方式不好,导致wa了。可能别人的代码看多了吧,代码能力不行,以后要多写题练练。