bzoj3307 雨天的尾巴
Posted 逢山开路 遇水架桥
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj3307 雨天的尾巴相关的知识,希望对你有一定的参考价值。
传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=3307
【题解】
这什么垃圾题啊卡空间卡时间卡栈
然后我会了一种新姿势:人工栈(好像也不难啊喂)
我们发现对于每种物品,只需要在u这地方的权值线段树上+1,v的权值线段树上+1,LCA的权值线段树上-1,LCA的父亲权值线段树上-1.
算一算就会发现符合条件了。
现在需要的就是合并线段树
线段树合并是log的,然后就是O(nlogn)了
bzoj上恰好10s。。
还有一个是,本地实测,极限数据要开到1000w才能过,bzoj卡了空间我只能开600w,居然过了。。
放两个代码吧(虽然bzoj都能过?)
直接dfs,开栈命令(?)
# pragma comment(linker, /STACK:102400000,102400000) # include <queue> # include <stdio.h> # include <string.h> # include <iostream> # include <algorithm> // # include <bits/stdc++.h> using namespace std; typedef long long ll; typedef long double ld; typedef unsigned long long ull; const int M = 2e5 + 10, N = 6e6 + 10; const int mod = 1e9+7; # define RG register # define ST static namespace SMT { int p[N], w[N], ch[N][2], siz; inline void up(int x) { if(w[ch[x][0]] >= w[ch[x][1]]) { w[x] = w[ch[x][0]]; p[x] = p[ch[x][0]]; } else { w[x] = w[ch[x][1]]; p[x] = p[ch[x][1]]; } } inline void edt(int &x, int l, int r, int pos, int d) { if(!x) x = ++siz; if(l == r) { p[x] = l; w[x] += d; return ; } int mid = l+r>>1; if(pos <= mid) edt(ch[x][0], l, mid, pos, d); else edt(ch[x][1], mid+1, r, pos, d); up(x); } inline int merge(int x, int y, int l, int r) { if(!x || !y) return x+y; if(l == r) { w[x] = w[x] + w[y]; return x; } int mid = l+r>>1; ch[x][0] = merge(ch[x][0], ch[y][0], l, mid); ch[x][1] = merge(ch[x][1], ch[y][1], mid+1, r); up(x); return x; } } int head[M], nxt[M], to[M], tot=0; inline void add(int u, int v) { ++tot; nxt[tot] = head[u]; head[u] = tot; to[tot] = v; } inline void adde(int u, int v) { add(u, v), add(v, u); } int n, m, rt[M]; int fa[M][17], dep[M]; inline void dfs(int x, int father) { dep[x] = dep[father] + 1; fa[x][0] = father; for (int i=1; i<=16; ++i) fa[x][i] = fa[fa[x][i-1]][i-1]; for (int i=head[x]; i; i=nxt[i]) { if(to[i] == father) continue; dfs(to[i], x); } } inline int lca(int u, int v) { if(dep[u] < dep[v]) swap(u, v); for (int i=16; ~i; --i) if((dep[u]-dep[v]) & (1<<i)) u = fa[u][i]; if(u == v) return u; for (int i=16; ~i; --i) if(fa[u][i] != fa[v][i]) { u = fa[u][i]; v = fa[v][i]; } return fa[u][0]; } int ans[M]; inline void gans(int x) { for (int i=head[x]; i; i=nxt[i]) { if(to[i] == fa[x][0]) continue; gans(to[i]); rt[x] = SMT::merge(rt[x], rt[to[i]], 1, 1e9); } ans[x] = SMT::p[rt[x]]; } int main() { // freopen("3307.in", "r", stdin); // freopen("3307.out", "w", stdout); cin >> n >> m; for (int i=1, u, v; i<n; ++i) { scanf("%d%d", &u, &v); adde(u, v); } dfs(1, 0); for (int i=1, u, v, z; i<=m; ++i) { scanf("%d%d%d", &u, &v, &z); int LCA = lca(u, v); SMT::edt(rt[u], 1, 1e9, z, 1); SMT::edt(rt[v], 1, 1e9, z, 1); SMT::edt(rt[LCA], 1, 1e9, z, -1); if(LCA != 1) SMT::edt(rt[fa[LCA][0]], 1, 1e9, z, -1); } gans(1); for (int i=1; i<=n; ++i) printf("%d\n", ans[i]); return 0; }
人工栈
# include <queue> # include <stdio.h> # include <string.h> # include <iostream> # include <algorithm> // # include <bits/stdc++.h> using namespace std; typedef long long ll; typedef long double ld; typedef unsigned long long ull; const int M = 2e5 + 10, N = 6e6 + 10; const int mod = 1e9+7; # define RG register # define ST static namespace SMT { int p[N], w[N], ch[N][2], siz; inline void up(int x) { if(w[ch[x][0]] >= w[ch[x][1]]) { w[x] = w[ch[x][0]]; p[x] = p[ch[x][0]]; } else { w[x] = w[ch[x][1]]; p[x] = p[ch[x][1]]; } } inline void edt(int &x, int l, int r, int pos, int d) { if(!x) x = ++siz; if(l == r) { w[x] += d; if(w[x] <= 0) p[x] = 0; else p[x] = l; return ; } int mid = l+r>>1; if(pos <= mid) edt(ch[x][0], l, mid, pos, d); else edt(ch[x][1], mid+1, r, pos, d); up(x); } inline int merge(int x, int y, int l, int r) { if(!x || !y) return x+y; if(l == r) { w[x] = w[x] + w[y]; if(w[x] <= 0) p[x] = 0; else p[x] = l; return x; } int mid = l+r>>1; ch[x][0] = merge(ch[x][0], ch[y][0], l, mid); ch[x][1] = merge(ch[x][1], ch[y][1], mid+1, r); up(x); return x; } inline void prt(int x, int l, int r) { if(!x) return ; printf("%d %d %d %d %d\n", x, l, r, p[x], w[x]); if(l == r) return; int mid = l+r>>1; prt(ch[x][0], l, mid); prt(ch[x][1], mid+1, r); } } int head[M], nxt[M], to[M], tot=0; inline void add(int u, int v) { ++tot; nxt[tot] = head[u]; head[u] = tot; to[tot] = v; } inline void adde(int u, int v) { add(u, v), add(v, u); } int n, m, rt[M]; int fa[M][17], dep[M]; bool vis[M]; queue<int> q; inline void bfs(int x) { q.push(x); dep[x] = 1; while(!q.empty()) { int top = q.front(); q.pop(); vis[top] = 1; for (int i=1; i<=16; ++i) fa[top][i] = fa[fa[top][i-1]][i-1]; for (int i=head[top]; i; i=nxt[i]) { if(!vis[to[i]]) { fa[to[i]][0] = top; dep[to[i]] = dep[top] + 1; q.push(to[i]); } } } } inline int lca(int u, int v) { if(dep[u] < dep[v]) swap(u, v); for (int i=16; ~i; --i) if((dep[u]-dep[v]) & (1<<i)) u = fa[u][i]; if(u == v) return u; for (int i=16; ~i; --i) if(fa[u][i] != fa[v][i]) { u = fa[u][i]; v = fa[v][i]; } return fa[u][0]; } int ans[M]; int st[M], cur[M], stn=0; inline void gans(int start) { int x, t; st[++stn] = start; while(stn) { x = st[stn]; if(to[cur[x]] == fa[x][0]) cur[x] = nxt[cur[x]]; if(!cur[x]) { --stn; ans[x] = SMT::p[rt[x]]; // printf("==================%d=================\n", x); // SMT::prt(rt[x], 1, 1e9); t = fa[x][0]; if(t) rt[t] = SMT::merge(rt[t], rt[x], 1, 1e9); } else { t = to[cur[x]]; st[++stn] = t; cur[x] = nxt[cur[x]]; } } } int main() { // freopen("3307.in", "r", stdin); // freopen("3307.out", "w", stdout); cin >> n >> m; for (int i=1, u, v; i<n; ++i) { scanf("%d%d", &u, &v); adde(u, v); } bfs(1); for (int i=1, u, v, z; i<=m; ++i) { scanf("%d%d%d", &u, &v, &z); int LCA = lca(u, v); SMT::edt(rt[u], 1, 1e9, z, 1); SMT::edt(rt[v], 1, 1e9, z, 1); SMT::edt(rt[LCA], 1, 1e9, z, -1); if(LCA != 1) SMT::edt(rt[fa[LCA][0]], 1, 1e9, z, -1); } for (int i=1; i<=n; ++i) cur[i] = head[i]; gans(1); for (int i=1; i<=n; ++i) printf("%d\n", ans[i]); return 0; } /* 5 5 1 2 2 3 3 4 4 5 1 2 1 2 3 1 1 3 1 1 4 2 3 4 2 */
以上是关于bzoj3307 雨天的尾巴的主要内容,如果未能解决你的问题,请参考以下文章