技术标签: 树结构
换根树链剖分
ll son[maxn], siz[maxn], fa[maxn], top[maxn], dep[maxn], val[maxn];
ll in[maxn], out[maxn], tot, pos[maxn];
ll root;
ll sum[maxn << 2], add[maxn << 2];
ll n, m;
struct Edge
{
ll u, v, next;
} edges[maxn];
ll heads[maxn], tot1;
void addEdge(ll u, ll v)
{
edges[++tot1].next = heads[u];
edges[tot1].u = u;
edges[tot1].v = v;
heads[u] = tot1;
}
void dfs1(ll u)
{
siz[u] = 1;
for (ll i = heads[u]; i; i = edges[i].next)
{
ll v = edges[i].v;
if (v == fa[u])
continue;
fa[v] = u;
dep[v] = dep[u] + 1;
dfs1(v);
siz[u] += siz[v];
if (siz[v] > siz[son[u]])
son[u] = v;
}
}
void dfs2(ll u)
{
in[u] = ++tot;
pos[tot] = u;
if (son[u])
{
top[son[u]] = top[u];
dfs2(son[u]);
}
for (ll i = heads[u]; i; i = edges[i].next)
{
ll v = edges[i].v;
if (v == fa[u] || v == son[u])
continue;
top[v] = v;
dfs2(v);
}
out[u] = tot;
}
ll LCA(ll u, ll v)
{
while (top[u] != top[v])
{
if (dep[top[u]] > dep[top[v]])
swap(u, v);
v = fa[top[v]];
}
return dep[u] > dep[v] ? v : u;
}
void pushup(ll k)
{
sum[k] = sum[k << 1] + sum[k << 1 | 1];
}
void pushnow(ll k, ll l, ll r, ll val)
{
add[k] += val;
sum[k] += 1ll * (r - l + 1) * val;
}
void pushdown(ll k, ll l, ll r)
{
if (add[k])
{
ll mid = (l + r) >> 1;
pushnow(k << 1, l, mid, add[k]);
pushnow(k << 1 | 1, mid + 1, r, add[k]);
add[k] = 0;
}
}
void build(ll k, ll l, ll r)
{
if (l == r)
{
sum[k] = val[pos[l]];
return;
}
ll mid = (l + r) >> 1;
build(k << 1, l, mid);
build(k << 1 | 1, mid + 1, r);
pushup(k);
}
ll query(ll k, ll l, ll r, ll ql, ll qr)
{
if (ql <= l && r <= qr)
return sum[k];
pushdown(k, l, r);
ll mid = (l + r) >> 1;
if (qr <= mid)
return query(k << 1, l, mid, ql, qr);
if (mid < ql)
return query(k << 1 | 1, mid + 1, r, ql, qr);
return query(k << 1, l, mid, ql, qr) + query(k << 1 | 1, mid + 1, r, ql, qr);
}
void modify(ll k, ll l, ll r, ll ql, ll qr, ll val)
{
if (ql <= l && r <= qr)
return pushnow(k, l, r, val);
pushdown(k, l, r);
ll mid = (l + r) >> 1;
if (ql <= mid)
modify(k << 1, l, mid, ql, qr, val);
if (qr > mid)
modify(k << 1 | 1, mid + 1, r, ql, qr, val);
pushup(k);
}
void addpath(ll u, ll v, ll val)
{
while (top[u] != top[v])
{
if (dep[top[v]] > dep[top[u]])
swap(u, v);
modify(1, 1, n, in[top[u]], in[u], val);
u = fa[top[u]];
}
if (dep[u] < dep[v])
swap(u, v);
modify(1, 1, n, in[v], in[u], val);
}
ll querypath(ll u, ll v)
{
ll res = 0;
while (top[u] != top[v])
{
if (dep[top[u]] < dep[top[v]])
swap(u, v);
res += query(1, 1, n, in[top[u]], in[u]);
u = fa[top[u]];
}
if (dep[u] < dep[v])
swap(u, v);
return res + query(1, 1, n, in[v], in[u]);
}
ll find(ll u, ll v)
{
while (top[u] != top[v])
{
if (dep[top[u]] < dep[top[v]])
swap(u, v);
if (fa[top[u]] == v)
return top[u];
u = fa[top[u]];
}
if (dep[u] < dep[v])
swap(u, v);
return son[v];
}
void addsubtree(ll u, ll val)
{
if (u == root)
return modify(1, 1, n, 1, n, val);
ll lca = LCA(u, root);
if (lca != u)
return modify(1, 1, n, in[u], out[u], val);
ll son = find(u, root);
modify(1, 1, n, 1, n, val);
modify(1, 1, n, in[son], out[son], -val);
}
ll querysubtree(ll u)
{
if (u == root)
return query(1, 1, n, 1, n);
ll lca = LCA(u, root);
if (lca != u)
return query(1, 1, n, in[u], out[u]);
ll son = find(u, root);
return query(1, 1, n, 1, n) - query(1, 1, n, in[son], out[son]);
}
signed main()
{
scanf("%lld%lld", &n, &m);
for (ll i = 1; i <= n; i++)
{
scanf("%lld", &val[i]);
}
for (ll i = 2; i <= n; i++)
{
ll u, v;
scanf("%lld%lld", &u, &v);
addEdge(u, v);
addEdge(v, u);
}
root = 1;
dfs1(root);
top[1] = 1;
dfs2(1);
build(1, 1, n);
while (m--)
{
ll op;
scanf("%lld", &op);
if (op == 1)//换根
{
ll u;
scanf("%lld", &u);
root = u;
}
else if (op == 2)//找换根LCA更改子树
{
ll u, v;
scanf("%lld%lld", &u, &v);
ll val;
scanf("%lld", &val);
ll zu1=LCA(u, root);
ll zu2=LCA(v, root);
ll zu;
if(zu1!=zu2)
{
if(dep[zu1]>dep[zu2])
{
zu=zu1;
}
else
{
zu=zu2;
}
}
else
{
zu=LCA(u,v);
}
// printf("zu:%lld\n", zu);
addsubtree(zu, val);
}
else//查询子树和
{
ll u;
scanf("%lld", &u);
printf("%lld\n", querysubtree(u));
}
}
return 0;
}
可持久化trie树
struct Trie
{
ll tr[maxn * 32][2], cnt[maxn * 32], idx;
void insert(ll &u, ll p, ll val, ll len)
{
u = ++idx;
ll q = u;
for (ll i = len; i >= 0; i--)
{
cnt[q] = cnt[p] + 1;
ll v = (val >> i & 1);
tr[q][v ^ 1] = tr[p][v ^ 1];
tr[q][v] = ++idx;
q = tr[q][v], p = tr[p][v];
}
cnt[q] = cnt[p] + 1;
}
ll query(ll p, ll q, ll val, ll k, ll len) //从p到q异或上val的第k小的值
{
ll res = 0;
for (ll i = len; i >= 0; i--)
{
ll v = (val >> i & 1);
ll num = cnt[tr[q][v ^ 1]] - cnt[tr[p][v ^ 1]];
if (num < k)
k -= num, p = tr[p][v], q = tr[q][v];
else
res += (1 << i), p = tr[p][v ^ 1], q = tr[q][v ^ 1];
}
return res;
}
} trie;
trie.insert(root[x], root[x-1], arr[x], 31);
printf("%lld\n", trie.query(root[l-1], root[r], val, k, 31));
树上启发式合并
void go(ll u,ll fa,ll type)
{
cnt[arr[u]]+=type;
if(type==1&&cnt[arr[u]]==1) ans++;
if(type==-1&&cnt[arr[u]]==0) ans--;
for(auto v:to[u])
{
if(v==fa) continue;
go(v,u,type);
}
}
void dfs3(ll u, ll fa, ll del)//del是否需要删除
{
for(auto v:to[u])
{
if(v==fa||v==son[u]) continue;
dfs3(v,u,1);
}
if(son[u]!=0)
{
dfs3(son[u],u,0);
}
cnt[arr[u]]++; if(cnt[arr[u]]==1) ans++;
for(auto v:to[u])
{
if(v==fa||v==son[u]) continue;
go(v,u,1);
}
dp[u]=ans;
if(del)
{
go(u,fa,-1);
}
}
树链剖分
ll n, m, r, p, cnt;
ll arr[maxn], dep[maxn], fa[maxn], siz[maxn];
ll son[maxn], id[maxn], w[maxn], top[maxn], sum[maxn << 2], add[maxn << 2];
vector<ll> to[maxn];
void dfs1(ll now, ll fath)
{
// printf("*1\n");
dep[now] = dep[fath] + 1;
fa[now] = fath;
siz[now] = 1;
ll maxson = -1;
for (auto v : to[now])
{
if (v == fath)
continue;
dfs1(v, now);
siz[now] += siz[v];
if (siz[v] > maxson)
{
son[now] = v;
maxson = siz[v];
}
}
}
void dfs2(ll now, ll topf)
{
id[now] = ++cnt;
w[cnt] = arr[now];
top[now] = topf;
if (!son[now])
{
return;
}
dfs2(son[now], topf);
for (auto v : to[now])
{
if (v == fa[now] || v == son[now])
{
continue;
}
dfs2(v, v);
}
}
void pushUp(ll rt)
{
sum[rt] = (sum[rt << 1] + sum[rt << 1 | 1]) % p;
}
void pushDown(ll rt, ll ln, ll rn)
{
if (add[rt])
{
sum[rt << 1] = (sum[rt << 1] + add[rt]*ln) % p;
sum[rt << 1 | 1] = (sum[rt << 1 | 1] + add[rt]*rn) % p;
add[rt << 1] = (add[rt << 1] + add[rt]) % p;
add[rt << 1 | 1] = (add[rt << 1 | 1] + add[rt]) % p;
add[rt] = 0;
}
}
void build(ll l, ll r, ll rt)
{
if (l == r)
{
sum[rt] = w[l] % p;
return;
}
ll m = (l + r) >> 1;
build(lson);
build(rson);
pushUp(rt);
}
void update(ll L, ll R, ll c, ll l, ll r, ll rt)
{
if (L <= l && r <= R)
{
sum[rt] = (sum[rt] + (r - l + 1) * c) % p;
add[rt] = (add[rt] + c) % p;
return;
}
ll m = (l + r) >> 1;
pushDown(rt, m - l + 1, r - m);
if (m >= L)
update(L, R, c, lson);
if (m < R)
update(L, R, c, rson);
pushUp(rt);
}
ll query(ll L, ll R, ll l, ll r, ll rt)
{
if (L <= l && r <= R)
{
return sum[rt];
}
ll m = (l + r) >> 1;
pushDown(rt, m - l + 1, r - m);
ll ans = 0;
if (m >= L)
ans += query(L, R, lson);
if (m < R)
ans += query(L, R, rson);
return ans%p;
}
void upd(ll x, ll y, ll c)
{
c %= p;
while (top[x] != top[y])
{
if (dep[top[x]] < dep[top[y]])
swap(x, y);
update(id[top[x]], id[x], c, 1, n,1);
x = fa[top[x]];
}
if (dep[x] > dep[y])
swap(x, y);
update(id[x], id[y], c, 1, n,1);
//update(id[x] + 1, id[y], c, 1, n);//边权转化为点权,避开LCA
}
ll qry(ll x, ll y)
{
ll ans = 0;
while (top[x] != top[y])
{
if (dep[top[x]] < dep[top[y]])
swap(x, y);
ans += query(id[top[x]], id[x], 1, n,1);
ans %= p;
x = fa[top[x]];
}
if (dep[x] > dep[y])
swap(x, y);
ans += query(id[x], id[y], 1, n,1);
ans %= p;
return ans;
}
void updSon(ll x, ll c)
{
update(id[x], id[x] + siz[x] - 1, c, 1, n,1);
}
ll qrySon(ll x)
{
return query(id[x], id[x] + siz[x] - 1, 1, n,1);
}
int main()
{
// DEBUG;
scanf("%lld%lld%lld%lld", &n, &m, &r, &p);
for (ll i = 1; i <= n; i++)
{
scanf("%lld", &arr[i]);
}
for (ll i = 1; i <= n - 1; i++)
{
ll u, v;
scanf("%lld%lld", &u, &v);
to[u].push_back(v);
to[v].push_back(u);
}
// printf("*1\n");
dfs1(r, 0);
// printf("*1\n");
dfs2(r, r);
build(1, n,1);
for (ll i = 1; i <= m; i++)
{
ll op;
scanf("%lld", &op);
if (op == 1)
{
ll x, y, c;
scanf("%lld%lld%lld", &x, &y, &c);
upd(x, y, c);
}
else if (op == 2)
{
ll x, y;
scanf("%lld%lld", &x, &y);
printf("%lld\n", qry(x, y)%p);
}
else if (op == 3)
{
ll x, c;
scanf("%lld%lld", &x, &c);
updSon(x, c);
}
else if (op == 4)
{
ll x;
scanf("%lld", &x);
printf("%lld\n", qrySon(x)%p);
}
}
}
二叉搜索树
const ll maxn = 1e3 + 10;
typedef struct Node *BinTree;
ll n, s = 0, t = 0, k = 0;
ll a[maxn], b[maxn], c[maxn];
struct Node
{
ll data;
BinTree left, right;
};
//建立二叉搜索树
BinTree CreatTree(BinTree BST, ll x)
{
if (!BST)
{
BST = new Node;
BST->data = x;
BST->left = BST->right = 0;
}
else
{
if (x < BST->data)
{
BST->left = CreatTree(BST->left, x);
}
else
{
BST->right = CreatTree(BST->right, x);
}
}
return BST;
}
//先序遍历
void PreorderTraversal(BinTree BST)
{
if (BST)
{
b[s++] = BST->data;
PreorderTraversal(BST->left);
PreorderTraversal(BST->right);
}
}
//镜面先序输出
void MirrorPreorderTraversal(BinTree BST)
{
if (BST)
{
c[t++] = BST->data;
MirrorPreorderTraversal(BST->right);
MirrorPreorderTraversal(BST->left);
}
}
//后序遍历
ll k1 = 0;
void PostorderTraversal(BinTree BST)
{
if (BST)
{
PostorderTraversal(BST->left);
PostorderTraversal(BST->right);
if (k1)
cout << " ";
cout << BST->data;
k1 = 1;
}
}
//镜面后序遍历
ll k2 = 0;
void MirrorPostorderTraversal(BinTree BST)
{
if (BST)
{
MirrorPostorderTraversal(BST->right);
MirrorPostorderTraversal(BST->left);
if (k2)
cout << " ";
cout << BST->data;
k2 = 1;
}
}
int main()
{
// DEBUG;
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
BinTree BST;
BST = NULL;
cin >> n;
for (ll i = 0; i < n; i++)
{
cin >> a[i];
BST = CreatTree(BST, a[i]);
}
PreorderTraversal(BST);
MirrorPreorderTraversal(BST);
ll flag1 = 1, flag2 = 1;
for (ll i = 0; i < n; i++)
{
if (a[i] != b[i])
{
flag1 = 0;
break;
}
}
for (ll i = 0; i < n; i++)
{
if (a[i] != c[i])
{
flag2 = 0;
break;
}
}
if (flag1 == 0 && flag2 == 0)
{
cout << "NO" << endl;
}
else
{
cout << "YES" << endl;
if (flag1)
{
PostorderTraversal(BST);
}
else
{
MirrorPostorderTraversal(BST);
}
}
return 0;
}
二叉树的建立,翻转即层次输出
const ll maxn = 30 + 10;
struct Node
{
ll data;
Tree left, right;
};
ll n;
ll fir[maxn], mid[maxn];
Tree creat(ll n, ll *fir, ll *mid)//由前序,中序建树
{
if (n == 0)
return 0;
Tree tree = new Node;
tree->data = fir[0];
tree->left = tree->right = NULL;
ll i = 0;
while (mid[i] != fir[0])
i++;
tree->left = creat(i, fir + 1, mid);
tree->right = creat(n - i - 1, fir + i + 1, mid + i + 1);
return tree;
}
Tree fanzhuan(Tree tree)//反转树
{
Tree t;
if (tree)
{
if (tree->left || tree->right)
{
t = tree->left;
tree->left = tree->right;
tree->right = t;
}
fanzhuan(tree->left);
fanzhuan(tree->right);
}
return tree;
}
void order(ll n,Tree tree)//层次输出
{
if(!n) return;
queue<Tree>que;
que.push(tree);
ll len=0;
while(!que.empty())
{
Tree temp=que.front();
que.pop();
if(!len)
{
cout<<temp->data;
len++;
}
else cout<<" "<<temp->data;
if(temp->left)
{
que.push(temp->left);
}
if(temp->right)
{
que.push(temp->right);
}
}
}
int main()
{
// DEBUG;
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin >> n;
for (ll i = 0; i < n; i++)
{
cin >> mid[i];
}
for (ll i = 0; i < n; i++)
{
cin >> fir[i];
}
Tree tree = creat(n, fir, mid);
tree=fanzhuan(tree);
order(n,tree);
return 0;
}
根据子树个数顺序中序排列建树
//设tree[i][0] 为第i个节点的左节点编号
//设tree[i][1] 为第i个节点的右节点编号
void dfs(int root){
//root表示几号节点
tot++;//表示总共访问了几个节点。
if (s[root]=='0') return;//叶子节点退出
if (s[root]=='1') {
tree[root][0]=root+1;//下一个访问的节点的编号一定是这个节点编号+1
dfs(root+1);//向下搜
}
if (s[root]=='2') {
tree[root][0]=root+1;
dfs(root+1);
tree[root][1]=tot+1;//右节点一定是总共访问的编号+1
dfs(tot+1);
}
}
随着英特尔第 12 代 Alder Lake-S 处理器计划在今年年底推出,下一代 DRAM 即将正式问世(内存厂商已量产或小批量DDR5),DDR5 将会以4,800Mbps 起步进入零售市场。相比之下,根据 JEDEC 规范,DDR4速度只能达到3,200Mbps。DDR5做了许多改变来提高内存传输频率。首先,增加BL将内存预取增加到 16;其次,将banks加倍到 32(每个 BG 2 或 4 个),同时还支持旧的 16 banks、刷新(基于每个bank刷新)和双通道 DIMM等:突发.
圣普伦将带大家了解6个顶级项目常用到的估算方法:类比估算、参数估算、德尔菲法、3 点估算、专家判断、供应商投标分析、自下而上的分析
项目背景:小程序视频显示的时候要显示一张默认的图片,点击之后会跳转播放视频,减少用户去选择上传封面的操作,所以就要服务端获取视频的第一帧当作封面。原理:ffmpeg功能特别强大,可以高效完美的处理视频和图片。实现过程:1,Linux下安装ffmpeg扩展(自己解决)2,安装完测试ffmpeg功能是否正常3,使用TP5 简单封装并调用ffmpeg功能完!...
方式1kill `ps -ef | grep 'test'` 方式2for pid in $(ps -aux | grep &quot;test&quot; | awk '{print $2}'); do kill -9 $pid; done 方式3ps -ef | grep 'test' | xargs kill
python3代码如下:import requestsimport timedef get_mercator(addr): url= 'http://api.map.baidu.com/geocoder/v2/?address=%s&amp;output=json&amp;ak=************************&amp;callback=showLocat...
Vi /etc/my.cof 增加一行 innodb_force_recovery= 1mysql非正常关机,无法启动!Error: could not open single-table tablespace file .\mysql\innodb_index_stats.ibd1. 进入mysql/data 目录2. 把下面的文件删除.......frm.......ibd重启my...
1.清华大学镜像下载https://mirrors.tuna.tsinghua.edu.cn/gitlab-ce/ubuntu/pool/xenial/main/g/gitlab-ce/2.安装sudo dpkg -i gitlab-ce_xxxx~omnibus-1_amd64.deb遇到错误: ssh depends on openssh-server; however: Package ...
final关键字final用于声明属性,方法和类属性:定义就必须直接赋值或者在构造方法中进行赋值,并且后期不能修改方法:子类不能被覆盖类:不能被定义为抽象类或者接口,不可被继承.final属性赋值:–在声明时同时赋值,往往与static一起使用final static int Num = 10;package com.nie.day5.demo06;public class Filal { //用于声明方法和类 //final修饰常量,常量值不能变,利用static
Win32核心编程
索引操作和列表同理arr = np.random.randint(0,100,size=(5,6))arrarray([[14, 89, 71, 96, 1, 94],[30, 98, 10, 64, 71, 54],[ 4, 80, 6, 27, 88, 3],[83, 75, 99, 24, 57, 37],[98, 24, 57, 42, 20, 21]])arr[1][3]64切片操...
为什么要搭建nexus私服,原因很简单,有些公司都不提供外网给项目组人员,因此就不能使用maven访问远程的仓库地址,所以很有必要在局域网里找一台有外网权限的机器,搭建nexus私服,然后开发人员连到这台私服上,这样的话就可以通过这台搭建了nexus私服的电脑访问maven的远程仓库。1.首先确定我们的环境安装好maven,jdk等必须的环境2.这些都准备好之后,去下载最...