18寒假第四测
Posted Ed_Sheeran
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了18寒假第四测相关的知识,希望对你有一定的参考价值。
problem 4 full
第一题:裸的树状数组
#include <cstdio> const int N = 100010; const int M = N + N; int n, q; int aa[N]; int head[N], dest[M], last[M], etot; int in[N], out[N], seq[N], idc; long long bit[N]; void adde( int u, int v ) { etot++; dest[etot] = v; last[etot] = head[u]; head[u] = etot; } void dfs( int u, int f ) { idc++; in[u] = idc; seq[idc] = u; for( int t = head[u]; t; t = last[t] ) { int v = dest[t]; if( v == f ) continue; dfs( v, u ); } out[u] = idc; } void modify( int pos, int delta ) { for( int i = pos; i <= n; i += i & -i ) bit[i] += delta; } long long query( int rg ) { long long rt = 0; for( int i = rg; i; i -= i & -i) { rt += bit[i]; } return rt; } long long query( int lf, int rg ) { return query(rg) - query(lf-1); } int main() { freopen("subtree.in", "r", stdin); freopen("subtree.out", "w", stdout); scanf( "%d", &n ); for( int i = 1; i <= n; i++ ) scanf( "%d", aa + i ); for( int i = 1; i < n; i++ ) { int u, v; scanf( "%d%d", &u, &v ); adde( u, v ); adde( v, u ); } idc = 0; dfs(1,1); for( int u = 1; u <= n; u++ ) { modify( in[u], aa[u] ); } scanf( "%d", &q ); while( q-- ) { char ss[100]; int u, d; scanf( "%s", ss ); if( ss[0] == \'m\' ) { scanf( "%d%d", &u, &d ); modify( in[u], d ); } else { scanf( "%d", &u ); printf( "%lld\\n", query( in[u], out[u] ) ); } } }
第二题:裸的树剖求LCA
#include<bits/stdc++.h> using namespace std; const int maxn = 100005; int a[maxn],head[maxn * 2],to[maxn * 2],next[maxn * 2];//2倍空间 int son[maxn], f[maxn], siz[maxn], top[maxn], dep[maxn]; int n, tot, idx, m; void adde(int u, int v){ ++tot; next[tot] = head[u]; to[tot] = v; head[u] = tot; } void dfs1(int u,int from){ siz[u] = 1; for(int i = head[u]; i; i = next[i]){ int v = to[i]; if(v != from){ f[v] = u; dep[v] = dep[u] + 1; dfs1(v, u); siz[u] += siz[v]; if(siz[v] > siz[son[u]]) son[u] = v; } } } void dfs2(int u,int from){ top[u] = from; if(son[u])dfs2(son[u], from); for(int i = head[u]; i; i = next[i]){ int v = to[i]; if(v == f[u] || v == son[u])continue;//f[u] != from ! dfs2(v, v); } } int lca(int u, int v){ while(top[u] != top[v]){ if(dep[top[u]] < dep[top[v]])swap(u, v);//dep[top] ! u = f[top[u]]; } return dep[u] < dep[v] ? u : v; } int main(){ freopen("dcplca.in","r",stdin); freopen("dcplca.out","w",stdout); //ios::sync_with_stdio(false); cin>>n; for(int i = 1; i < n; i++){ int u, v; scanf("%d%d",&u,&v); adde(u, v); adde(v, u); } dep[1] = f[1] =1; dfs1(1, 1); dfs2(1, 1); cin>>m; for(int i = 1; i <= m; i++){ int u,v; scanf("%d%d",&u,&v); printf("%d\\n",lca(u, v)); } }
第三题:线段树+树剖
#include<bits/stdc++.h> using namespace std; const int maxn = 100005; long long c[maxn]; int a[maxn],head[maxn * 2],to[maxn * 2],next[maxn * 2]; int son[maxn], in[maxn], out[maxn], f[maxn], siz[maxn], top[maxn], dep[maxn]; int n, tot, idx, m; void adde(int u, int v){ ++tot; next[tot] = head[u]; to[tot] = v; head[u] = tot; } struct SegmentTree{ struct node{ long long sum; int lazy; }; node Tree[maxn << 2]; #define ls l, m, v << 1 #define rs m+1, r, v << 1 | 1 void push_up(int v){ Tree[v].sum = Tree[v << 1].sum + Tree[v << 1 | 1].sum; } void push_down(int l,int r,int v){ int m = (l + r) >> 1; Tree[v << 1].sum += 1LL * Tree[v].lazy * (m - l + 1); Tree[v << 1].lazy += Tree[v].lazy; Tree[v << 1 | 1].sum += 1LL * Tree[v].lazy * (r - m); Tree[v << 1 | 1].lazy += Tree[v].lazy; Tree[v].lazy = 0; } void build(int l = 1, int r = n, int v = 1){ Tree[v].sum = Tree[v].lazy = 0; if(l == r) { Tree[v].sum = a[l] * 1LL; Tree[v].lazy = 0; } else { int m = (l + r) >> 1; build(ls); build(rs); push_up(v); } } void modify(int x,int L,int R,int l = 1, int r = n,int v = 1){ if(l >= L && r <= R) Tree[v].sum += 1LL * x * (r - l + 1), Tree[v].lazy += x; else { if(Tree[v].lazy)push_down(l,r,v); int m = (l + r) >> 1; if(L <= m) modify(x,L,R,ls); if(R > m) modify(x,L,R,rs); push_up(v); } } long long query(int L,int R,int l = 1, int r = n,int v = 1){ if(l >= L && r <= R) return Tree[v].sum ; else { if(Tree[v].lazy)push_down(l,r,v); int m = (l + r) >> 1; long long ans = 0; if(L <= m) ans += query(L,R,ls); if(R > m) ans += query(L,R,rs); return ans; } } }; SegmentTree Tr; void dfs1(int u,int from){ siz[u] = 1; for(int i = head[u]; i; i = next[i]){ int v = to[i]; if(v != from){ f[v] = u; dep[v] = dep[u] + 1; dfs1(v, u); siz[u] += siz[v]; if(siz[v] > siz[son[u]]) son[u] = v; } } } void dfs2(int u,int from){ in[u] = ++idx; a[idx] = c[u]; top[u] = from; if(son[u])dfs2(son[u], from); for(int i = head[u]; i; i = next[i]){ int v = to[i]; if(v == f[u] || v == son[u])continue;//f[u] != from ! dfs2(v, v); } out[u] = idx; } long long lca1(int u, int v){ long long ans = 0; while(top[u] != top[v]){ if(dep[top[u]] < dep[top[v]])//dep[top]! swap(u, v); ans += Tr.query(in[top[u]], in[u]); u = f[top[u]]; } if(dep[u] < dep[v])swap(u,v); ans += Tr.query(in[v], in[u]); return ans; } void lca2(int u, int v,int x){ long long ans = 0; while(top[u] != top[v]){ if(dep[top[u]] < dep[top[v]])//dep[top]! swap(u, v); Tr.modify(x, in[top[u]], in[u]); u = f[top[u]]; } if(dep[u] < dep[v])swap(u,v); Tr.modify(x, in[v], in[u]); } void init(){ cin>>n; for(int i = 1; i <= n; i++) scanf("%d",c + i); for(int i = 1; i < n; i++){ int u, v; scanf("%d%d",&u,&v); adde(u, v); adde(v, u); } dep[1] = f[1] = 1; dfs1(1,1); dfs2(1,1); Tr.build(); } void work(){ cin>>m; for(int i = 1; i <= m; i++){ string opt; cin>>opt; if(opt == "msub"){ int u,x; scanf("%d%d",&u,&x); Tr.modify(x,in[u],out[u]); } if(opt == "mpth"){ int u,x,v; scanf("%d%d%d",&u,&v,&x); lca2(u,v,x); } if(opt == "qsub"){ int u; scanf("%d",&u); cout<<Tr.query(in[u],out[u])<<endl; } if(opt == "qpth"){ int u,v; scanf("%d%d",&u,&v); cout<<lca1(u, v)<<endl; } } } int main(){ freopen("full.in","r",stdin); freopen("full.out","w",stdout); init(); work(); }
以上是关于18寒假第四测的主要内容,如果未能解决你的问题,请参考以下文章