Wannafly挑战赛4-dfs序&线段树|搜索&思维|BIT-树的距离
来源:互联网 发布:熊猫tv送假佛跳墙软件 编辑:程序博客网 时间:2024/06/12 12:22
https://www.nowcoder.com/acm/contest/35/D
dfs序那个方法是标准做法。但是不知道怎么去用线段树搞。
给定一个树(根为1),然后给你 x和k,要求你求x为根的子树中 距离x大于等于k的点的 和。
一看子树,就知道是dfs序。关键是如何搞线段树orBIT ,把距离根节点的值 映射到 线段树上后(线段树的下标意义代表时间。)
维护最大值和最小值和 和(即线段树子树内的和qwq)。 还是没有特别专注这种东西。不错的题。
② 第二种方法,是dfs维护 距离根长度,x子树内的节点和x的距离和。
另外还要维护 fa(每个节点的父亲节点,因为后来用bfs计算的时候可以应用,不然就要麻烦一点)
用bfs计算节点的时候,因为递归性。
(如图,如果一个点距离x点已经大于等于k,那么他的子节点必然,所以我们如果计算好后,直接加就行),否则的话,就要累加距离,然后再进一步的递归计算。
这其实比单纯的bfs要快好多了,因为开始维护的sums数组。
ps:写的其实比较蠢笨。因为u22 这个,直接用x代替就好,累加的永远是和 x的距离qwq。u22永远只能是x。。
#include <iostream>#include <stdio.h>#include <string.h>#include <queue>using namespace std;/* 可以通过一个 dfs维护两个变量。一个 节点距离根节点的 距离len[u].另一个是 节点内的点距离 节点的距离和 sum[u].因为我们发现了一个递归的性质,如果一个点距离 x节点的距离大于等于k。那么他的子节点也是。我们可以统计一个长度再bfs里。*/typedef long long ll;const int maxn=2e5*2+200;int m;int len;struct Node{ int to,next,cos;}node[maxn];int head[maxn];void add(int a,int b,int c){ node[len].to=b; node[len].next=head[a]; node[len].cos=c; head[a]=len++;}ll lens[maxn];ll sums[maxn];int siz[maxn];int fa[maxn];void init(){ memset(head,-1,sizeof(head)); len=0;}void dfs(int u,int fas){ sums[u]=0; siz[u]=1;//ben jiedian. for(int i=head[u];i!=-1;i=node[i].next){ int to=node[i].to; int cost=node[i].cos; if(to==fas) continue; fa[to]=u;//这个再bfs的时候有一点用处。 lens[to]=lens[u]+1ll*cost; dfs(to,u); siz[u]+=siz[to]; sums[u]+=sums[to]+(1ll*siz[to]*cost); }}void bfs(int x,int k){ ll ans=0; queue<pair<int,int> >q; q.push(make_pair(x,x)); while(!q.empty()){ int u=q.front().first; int u22=q.front().second; q.pop(); for(int i=head[u];i!=-1;i=node[i].next){ int to=node[i].to; int cost=node[i].cos; if(to==fa[u]) continue; if(lens[to]-lens[u22]>=1ll*k){ ans=ans+(sums[to]+1ll*siz[to]*(lens[to]-lens[u22])); } else{ q.push(make_pair(to,u22)); } } } printf("%lld\n",ans);}int main(){ int a,b,x,k,n; scanf("%d",&m); init(); for(int i=1;i<m;i++){ scanf("%d%d",&a,&b); add(a,i+1,b); add(i+1,a,b); } dfs(1,-1); /*for(int i=1;i<=m;i++){ cout<<s7ums[i]<<" "<<siz[i]<<"??len"<<lens[i]<<endl; }*/ scanf("%d",&n); while(n--){ scanf("%d%d",&x,&k); bfs(x,k); } return 0;}
线段树代码是别人的。还有一个bit的。 那个类写的特别骚气qwq
#include <bits/stdc++.h>using namespace std;typedef long long LL;const int maxn = 200010;struct edge{ int to,next; LL cost;}E[maxn*2];int head[maxn], edgecnt;void init(){ memset(head, -1, sizeof(head)); edgecnt = 0;}void add(int u, int v, LL w){ E[edgecnt].to = v, E[edgecnt].next = head[u], E[edgecnt].cost = w, head[u] = edgecnt++;}int L[maxn], R[maxn], dfs_clk;LL a[maxn], d[maxn];struct node{ int l, r; LL minn, maxx, sum;}Tree[maxn<<2];void dfs(int u, int pre){ L[u] = ++dfs_clk; for(int i=head[u]; ~i; i=E[i].next){ int v = E[i].to; if(v == pre) continue; d[v] = d[u] + E[i].cost; dfs(v, u); } R[u] = dfs_clk;}void push_up(int rt){ Tree[rt].maxx = max(Tree[rt*2].maxx, Tree[rt*2+1].maxx); Tree[rt].minn = min(Tree[rt*2].minn, Tree[rt*2+1].minn); Tree[rt].sum = Tree[rt*2].sum + Tree[rt*2+1].sum;}void build(int l, int r, int rt){ Tree[rt].l = l, Tree[rt].r = r; if(l == r){ Tree[rt].maxx = Tree[rt].minn = Tree[rt].sum = a[l]; return; } int mid = l+r>>1; build(l, mid, rt*2); build(mid+1, r, rt*2+1); push_up(rt);}LL query(int L, int R, LL s, LL v, int rt){ if(L<=Tree[rt].l && Tree[rt].r<=R){ if(Tree[rt].minn>=v) return Tree[rt].sum - 1LL*s*(Tree[rt].r-Tree[rt].l+1); if(Tree[rt].maxx<v) return 0; } int mid = (Tree[rt].l+Tree[rt].r)/2; if(R<=mid) return query(L, R, s, v, rt*2); else if(L>mid) return query(L, R, s, v, rt*2+1); else return query(L, mid, s, v, rt*2) + query(mid+1, R, s, v, rt*2+1);}int main(){ init(); int n; scanf("%d", &n); for(int i=2; i<=n; i++){ int p; LL x; scanf("%d %lld", &p, &x); add(p, i, x); //add(i, p, x); } dfs(1, -1); for(int i=1; i<=n; i++) a[L[i]] = d[i]; build(1, n, 1); int q; scanf("%d", &q); while(q--){ int x; LL k; scanf("%d %lld", &x, &k); LL ans = query(L[x], R[x], d[x], d[x]+k, 1); printf("%lld\n", ans); } return 0;}
③别人家的BIT
#include <bits/stdc++.h>using namespace std;#define endl "\n"const int N = 1e6 + 8;int lt[N], sum, tot, n, q;long long ans[N];struct BIT{ long long a[N]; void insert(int pos, long long val) { pos++; for (int i = pos; i <= n + 1; i += i & (-i)) a[i] += val; } long long sigma(int pos) { long long res = 0; for (int i = pos; i > 0; i -= i & (-i)) res += a[i]; return res; } long long query(int l, int r) { l++; r++; if (l == 0) return sigma(r); return sigma(r) - sigma(l - 1); }}T1, T2;struct edge{ int v, w, nt;}eg[N << 1];struct query{ long long x; int id, w, size; long long dis; bool operator <(const query &b) const { return x < b.x; } void print() { cout << x << " " << id << " " << w << " " << size << " " << dis << endl; }}Q[N];struct node{ long long dis; int w, size; bool operator < (const node &b) const { return dis < b.dis; } void print() { cout << dis << " " << w << " " << size << endl; }}a[N];void add(int u, int v, int w){ eg[++sum] = (edge){v, w, lt[u]}; lt[u] = sum;}void dfs(int u){ a[u].w = ++tot; a[u].size = 1; for (int i = lt[u]; i; i = eg[i].nt) { a[eg[i].v].dis = a[u].dis + eg[i].w; dfs(eg[i].v); a[u].size += a[eg[i].v].size; }}void init(){ cin >> n; for (int i = 1; i <= n; ++i) lt[i] = 0; sum = 1; tot = 0; for (int i = 1; i < n; ++i) { int v, w; cin >> v >> w; add(v, i + 1, w); } dfs(1); cin >> q; for (int i = 1; i <= q; ++i) { int x, k; cin >> x >> k; Q[i].id = i; Q[i].x = a[x].dis + k; Q[i].w = a[x].w; Q[i].size = a[x].size; Q[i].dis = a[x].dis; } sort(Q + 1, Q + q + 1); sort(a + 1, a + n + 1);}void solve(){ for (int i = q, j = n; i >= 1; --i) { while (j > 0 && a[j].dis >= Q[i].x) { T1.insert(a[j].w, 1); T2.insert(a[j].w, a[j].dis); j--; } int num = T1.query(Q[i].w, Q[i].w + Q[i].size - 1); long long sum = T2.query(Q[i].w, Q[i].w + Q[i].size - 1); ans[Q[i].id] = sum - num * Q[i].dis; } for (int i = 1; i <= q; ++i) cout << ans[i] << endl;}int main(){ cin.sync_with_stdio(0); init(); solve();}
阅读全文
0 0
- Wannafly挑战赛4-dfs序&线段树|搜索&思维|BIT-树的距离
- Wannafly挑战赛4 D 树的距离
- Wannafly挑战赛2 C 思维 + 线段树
- newCoder Wannafly挑战赛4:D 树的距离(补)
- wannafly挑战赛4 C-割草机 思维
- wannafly挑战赛4C-水题&思维-割草机
- Wannafly挑战赛1 MMset2(虚树+树的直径)
- wannafly挑战赛4
- Wannafly挑战赛4
- Wannafly挑战赛4
- Wannafly挑战赛1 B.Xorto【思维+二分】
- nowcoder Wannafly挑战赛1 B 【暴力 + 思维】
- Wannafly挑战赛2 B 思维 + 最短路
- Wannafly挑战赛2 B.Travel【思维+SPFA】
- 【Wannafly挑战赛1 】B Xorto 【思维+二分】
- Wannafly挑战赛6 D-锁 思维
- Wannafly挑战赛1 A.Treepath(dfs)
- DFS 2568 hdu (树中两点距离的搜索)
- java线程池
- react状态提升 父子组件交互
- 我的Android征途
- 利用WGET下载文件,并保存到指定目录
- eclipse的uml工具之Papyrus 安装地址
- Wannafly挑战赛4-dfs序&线段树|搜索&思维|BIT-树的距离
- App接口测试总结
- C语言中的静态变量和非静态变量
- 宇宙最强VisualStudio2017配置pyQt5用于python3.6的UI界面工具
- 慕课网java反射
- 基于Dragonboard 410c的指纹锁(三)
- Linux 中的locate命令是怎样保持更新的
- 文章标题
- android学习路径