树链剖分

洛谷P2590

树链剖分模板题:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=50005;
int n,q;
int w[maxn];//每个点的权值
int father[maxn];//每个点的父亲 
int son[maxn]; //每个点的重儿子是谁
int id[maxn];//使用线段树是的节点编号要用id[]存
int pre[maxn];//将重新编号的节点映射回来 
int top[maxn];//每条树链的顶点
int deep[maxn]; 
int sz[maxn];//每个点的子树节点个数 
struct Node{
    int w;
    int maxx;
}tree[4*maxn]; 
vector<int>vec[maxn];
void init(){
    for(int i=1;i<n;i++){
        int u,v;
        cin>>u>>v;
        vec[u].push_back(v);
        vec[v].push_back(u);
    }
    for(int i=1;i<=n;i++){
        cin>>w[i];
    }
}
void dfs1(int u,int fa,int depth){
    father[u]=fa;
    deep[u]=depth;
    int max_son=-maxn;//记录重儿子个数 
    sz[u]=1;
    
    for(int i=0;i<vec[u].size();i++){
        int v=vec[u][i];
        if(v==fa)continue;
        dfs1(v,u,depth+1);
        sz[u]+=sz[v];
        if(sz[v]>max_son){
            max_son=sz[v];
            son[u]=v;
        } 
    }
}

int tot=0;
void dfs2(int u,int tp){
    top[u]=tp;
    id[u]=++tot;//重新编号u (先自增后访问)
    pre[tot]=u;//将编号映射回来
     
    if(son[u])dfs2(son[u],tp);
    
    for(int i=0;i<vec[u].size();i++){
        int v=vec[u][i];
        if(v==father[u]||v==son[u])continue;
        dfs2(v,v);
    }
}
void build(int L,int R,int k){
    if(L==R){
        tree[k].w=w[pre[L]];
        tree[k].maxx=w[pre[L]];
        return;
    }
    int mid=(L+R)/2;
    build(L,mid,2*k);
    build(mid+1,R,2*k+1); 
    
    tree[k].w=tree[2*k].w+tree[2*k+1].w;
    tree[k].maxx=max(tree[2*k].maxx,tree[2*k+1].maxx);
}
void update(int x,int t,int L,int R,int k){
    if(L==R&&L==x){
        tree[k].w=t;
        tree[k].maxx=t;
        return;
    }
    int mid=(L+R)/2;
    if(x<=mid)
        update(x,t,L,mid,2*k);
    else
        update(x,t,mid+1,R,2*k+1);
        
    tree[k].w=tree[2*k].w+tree[2*k+1].w;
    tree[k].maxx=max(tree[2*k].maxx,tree[2*k+1].maxx);
}
int query_max(int x,int y,int L,int R,int k){
    int ans=-maxn;
    if(R<=y&&L>=x){
        return tree[k].maxx;
    }
    int mid=(L+R)/2;
    if(x<=mid)
        ans=max(ans,query_max(x,y,L,mid,2*k));
    if(y>mid)
        ans=max(ans,query_max(x,y,mid+1,R,2*k+1));
    return ans;
}
int query_sum(int x,int y,int L,int R,int k){
    int ans=0;
    if(R<=y&&L>=x){
        return tree[k].w;
    }
    int mid=(L+R)/2;
    if(x<=mid)
        ans+=query_sum(x,y,L,mid,2*k);
    if(y>mid)
        ans+=query_sum(x,y,mid+1,R,2*k+1);
    return ans;
}

int QMAX(int u,int v){//查询点 u到点 v之间的最大值 
    int ans=-maxn;
    while(top[u]!=top[v]){//若 u和 v在不同链上 
        if(deep[top[u]]>deep[top[v]])
            swap(u,v);
        
        ans=max(ans,query_max(id[top[v]],id[v],1,n,1));
        v=father[top[v]];
    }
    if(deep[u]>deep[v])
        swap(u,v);
    ans=max(ans,query_max(id[u],id[v],1,n,1));
    return ans; 
}
int QSUM(int u,int v){
    int ans=0;
    while(top[u]!=top[v]){
        if(deep[top[u]]>deep[top[v]])
            swap(u,v);
        
        ans+=query_sum(id[top[v]],id[v],1,n,1);
        v=father[top[v]];
    }
    if(deep[u]>deep[v])
        swap(u,v);
    ans+=query_sum(id[u],id[v],1,n,1);
    return ans;
}
int main()
{
    ios::sync_with_stdio(false);
    cin>>n;
    init();
    
    int root=1;
    dfs1(root,0,1);//根节点,father,深度 
    dfs2(root,root);//dfs2找树链
    build(1,n,1);
    
    cin>>q;
    while(q--){
        string s;
        int u,v;
        cin>>s>>u>>v;
        if(s=="CHANGE")
            update(id[u],v,1,n,1);//把点 u改成 v 
        else if(s=="QMAX")
            cout<<QMAX(u,v)<<endl;
        else
            cout<<QSUM(u,v)<<endl;
    }
    return 0;
} 

 

codeforces 434D

题意:有一棵n个点,n-1条边构成的树,点权要么为1,要么为0,现在支持以下三种操作:

1、把某个点及其子树点权值全部赋值成1

2、把某个点及其祖先点权值全部赋值为0

3、查询某个点的点权

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod = 1e9 + 7;
const ll MAXN = 1e18 + 7;
const int maxn = 500000 + 10;
vector<int>vec[maxn];
int deep[maxn];
int top[maxn];
int father[maxn];
int son[maxn];
int pre[maxn];
int id[maxn];
int sz[maxn];
int n;
void init() {
	for (int i = 1; i<n; i++) {
		int u, v;
		cin >> u >> v;
		vec[u].push_back(v);
		vec[v].push_back(u);
	}
}
void dfs1(int u, int fa, int dep) {
	deep[u] = dep;
	father[u] = fa;
	sz[u] = 1;
	int max_son = -maxn;

	for (int i = 0; i<vec[u].size(); i++) {
		int v = vec[u][i];
		if (v == fa)continue;
		dfs1(v, u, dep + 1);
		sz[u] += sz[v];
		if (max_son<sz[v]) {
			max_son = sz[v];
			son[u] = v;
		}
	}
}
int tot = 0;
void dfs2(int u, int tp) {
	top[u] = tp;
	id[u] = ++tot;
	pre[tot] = u;

	if (son[u])dfs2(son[u], tp);
	for (int i = 0; i<vec[u].size(); i++) {
		int v = vec[u][i];
		if (v == father[u] || v == son[u])continue;
		dfs2(v, v);
	}
}
struct Node {
	int w;
	int lazy;
}tree[4 * maxn];
void pushdown(int k) {
	if (tree[k].lazy != -1) {
		tree[k<<1].lazy = tree[k << 1|1].lazy = tree[k].lazy;
		tree[k << 1].w = tree[k << 1| 1].w = tree[k].lazy;
		tree[k].lazy = -1;
	}
}
void build(int L, int R, int k) {
	tree[k].lazy = -1;//标记应该随时下放 
	if (L == R) {
		return;
	}
	int mid = (L + R) / 2;
	build(L, mid, 2 * k);
	build(mid + 1, R, 2 * k + 1);

}
void update_tree(int L, int R, int k, int x, int y, int ww) {
	if (x <= L&&y >= R) {
		tree[k].w = ww;
		tree[k].lazy = ww;
		return;
	}
	pushdown(k);
	int mid = (L + R) / 2;
	if (x <= mid)
		update_tree(L, mid, 2 * k, x, y, ww);
	if (y>mid)
		update_tree(mid + 1, R, 2 * k + 1, x, y, ww);
}

int query_tree(int L, int R, int k, int x) {
	if (L == R) {
		return tree[k].w;
	}
	pushdown(k);
	int mid = (L + R) / 2;
	if (x <= mid)
		return query_tree(L, mid, 2 * k, x);
	else
		return query_tree(mid + 1, R, 2 * k + 1, x);
}
void LCA(int u, int v) {//1是祖先 
	while (top[u] != top[v]) {
		if (deep[top[u]]>deep[top[v]])
			swap(u, v);
		update_tree(1, n, 1, id[top[v]], id[v], 0);
		v = father[top[v]];
	}

	if (deep[u]>deep[v])
		swap(u, v);
	update_tree(1, n, 1, id[u], id[v], 0);
}
int main()
{
	ios::sync_with_stdio(false);
	cin >> n;
	init();

	int root = 1;
	dfs1(root, -1, 1);
	dfs2(root, root);
	build(1, n, 1);

	int q;
	cin >> q;
	while (q--) {
		int cnt, v;
		cin >> cnt >> v;
		if (cnt == 1) 
			update_tree(1, n, 1, id[v], id[v] + sz[v] - 1, 1);//某一子树的序号一定连续 
		else if (cnt == 2) 
			LCA(1, v);
		else
			cout << query_tree(1, n, 1, id[v]) << endl;
	}
	return 0;
}

 

数据治理是确保数据准确性、可靠性、安全性、可用性和完整性的体系和框架。它定义了组织内部如何使用、存储、保护和共享数据的规则和流程。数据治理的重要性随着数字化转型的加速而日益凸显,它能够提高决策效率、增强业务竞争力、降低风险,并促进业务创新。有效的数据治理体系可以确保数据在采集、存储、处理、共享和保护等环节的合规性和有效性。 数据质量管理是数据治理中的关键环节,它涉及数据质量评估、数据清洗、标准化和监控。高质量的数据能够提升业务决策的准确性,优化业务流程,并挖掘潜在的商业价值。随着大数据和人工智能技术的发展,数据质量管理在确保数据准确性和可靠性方面的作用愈发重要。企业需要建立完善的数据质量管理和校验机制,并通过数据清洗和标准化提高数据质量。 数据安全与隐私保护是数据治理中的另一个重要领域。随着数据量的快速增长和互联网技术的迅速发展,数据安全与隐私保护面临前所未有的挑战。企业需要加强数据安全与隐私保护的法律法规和技术手段,采用数据加密、脱敏和备份恢复等技术手段,以及加强培训和教育,提高安全意识和技能水平。 数据流程管理与监控是确保数据质量、提高数据利用率、保护数据安全的重要环节。有效的数据流程管理可以确保数据流程的合规性和高效性,而实时监控则有助于及时发现并解决潜在问题。企业需要设计合理的数据流程架构,制定详细的数据管理流程规范,并运用数据审计和可视化技术手段进行监控。 数据资产管理是将数据视为组织的重要资产,通过有效的管理和利用,为组织带来经济价值。数据资产管理涵盖数据的整个生命周期,包括数据的创建、存储、处理、共享、使用和保护。它面临的挑战包括数据量的快速增长、数据类型的多样化和数据更新的迅速性。组织需要建立完善的数据管理体系,提高数据处理和分析能力,以应对这些挑战。同时,数据资产的分类与评估、共享与使用规范也是数据资产管理的重要组成部分,需要制定合理的标准和规范,确保数据共享的安全性和隐私保护,以及建立合理的利益分配和权益保障机制。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值