模拟赛 T3 dfs序+树状数组+树链的并+点权/边权技巧

code:

#include <vector>
#include <cstdio>
#include <set>
#include <cstring>
#include <string>
#include <algorithm>
#define N 200007
#define ll long long
using namespace std;
void setIO(string s) {
    string in=s+".in";
    string out=s+".out";
    freopen(in.c_str(),"r",stdin);
    freopen(out.c_str(),"w",stdout);
}
struct BIT {
    ll C[N];
    int lowbit(int t) {
        return t&(-t);
    }
    void update(int x,int v) {
        while(x<N) {
            C[x]+=(ll)v;
            x+=lowbit(x);
        }
    }
    ll query(int x) {
        ll tmp=0;
        while(x>0) {
            tmp+=C[x];
            x-=lowbit(x);
        }
        return tmp;
    }
}tree;
int tot;
int n,m,L;
int edges;
int dfn;
int hd[N];
int to[N<<1];
int nex[N<<1];
int top[N];
int son[N];
int size[N];
int dep[N];
int A[N];
int fa[N];
int st[N];
int ed[N];
int Fa[N];
vector<int>G[N];
bool cmp(int a,int b) {
    return st[a]<st[b];
}
void add(int u,int v) {
    nex[++edges]=hd[u];
    hd[u]=edges;
    to[edges]=v;
}
void dfs1(int u,int ff) {
    fa[u]=ff;
    size[u]=1;
    dep[u]=dep[ff]+1;
    for(int i=hd[u];i;i=nex[i]) {
        int v=to[i];
        if(v==ff) {
            continue;
        }
        dfs1(v,u);
        size[u]+=size[v];
        if(size[v]>size[son[u]]) {
            son[u]=v;
        }
    }
}
void dfs2(int u,int tp) {
    top[u]=tp;
    if(son[u]) {
        dfs2(son[u],tp);
    }
    for(int i=hd[u];i;i=nex[i]) {
        if(to[i]!=fa[u]&&to[i]!=son[u]) {
            dfs2(to[i],to[i]);
        }
    }
}
int LCA(int x,int y) {
    while(top[x]!=top[y]) {
        dep[top[x]]>dep[top[y]]?x=fa[top[x]]:y=fa[top[y]];
    }
    return dep[x]<dep[y]?x:y;
}
// 到根的权和
ll Sum(int x) {
    return tree.query(st[x]);
}
void build(int u) {
    for(int i=hd[u];i;i=nex[i]) {
        int v=to[i];
        if(v==fa[u]) {
            continue;
        }
        ++tot;
        Fa[tot]=u;
        Fa[v]=tot;
        G[u].push_back(tot);
        G[tot].push_back(v);
        build(v);
    }
}
void dfs(int u) {
    st[u]=++dfn;
    for(int i=0;i<G[u].size();++i) {
        int v=G[u][i];
        // printf("%d %d\n",u,v);
        dfs(v);
    }
    ed[u]=dfn;
}
int main() {
    setIO("tree");
    int i,j;
    scanf("%d%d%d",&n,&m,&L);
    for(i=1;i<n;++i) {
        int x,y;
        scanf("%d%d",&x,&y);
        add(x,y);
        add(y,x);
    }
    dfs1(1,0);
    dfs2(1,1);
    tot=n;
    build(1);
    dfs(1);
    while(m--) {
        int op;
        scanf("%d",&op);
        if(op==0) {
            int p,q,v,d=1;
            scanf("%d%d%d",&p,&q,&v);
            int lca=LCA(p,q);
            while(p!=lca) {
                tree.update(st[p],d*v);
                tree.update(ed[p]+1,-d*v);
                d*=-1;
                p=Fa[p];
            }
            d=1;
            while(q!=lca) {
                tree.update(st[q],d*v);
                tree.update(ed[q]+1,d*v);
                d*=-1;
                q=Fa[q];
            }
            tree.update(st[lca],v);
            tree.update(ed[lca]+1,-v);
        }
        else {
            int a,cnt=0;
            scanf("%d",&a);
            for(i=1;i<=a;++i) {
                scanf("%d",&A[++cnt]);
            }
            scanf("%d",&a);
            for(i=1;i<=a;++i) {
                scanf("%d",&A[++cnt]);
            }
            sort(A+1,A+1+cnt,cmp);
            int lca=A[1];
            for(i=2;i<=cnt;++i) {
                lca=LCA(lca,A[i]);
            }
            ll ans=0;
            for(i=1;i<=cnt;++i) {
                ans+=Sum(A[i])-Sum(Fa[lca]);
            }
            for(i=2;i<=cnt;++i) {
                ans-=Sum(LCA(A[i],A[i-1]))-Sum(Fa[lca]);
            }
            printf("%lld\n",ans);
        }
    }
    return 0;
}

  

原文地址:https://www.cnblogs.com/guangheli/p/12074444.html

时间: 2024-10-06 19:54:25

模拟赛 T3 dfs序+树状数组+树链的并+点权/边权技巧的相关文章

【BZOJ4785】[Zjoi2017]树状数组 树套树(二维线段树)

[BZOJ4785][Zjoi2017]树状数组 Description 漆黑的晚上,九条可怜躺在床上辗转反侧.难以入眠的她想起了若干年前她的一次悲惨的OI 比赛经历.那是一道基础的树状数组题.给出一个长度为 n 的数组 A,初始值都为 0,接下来进行 m 次操作,操作有两种: 1 x,表示将 Ax 变成 (Ax + 1) mod 2. 2 l r,表示询问 sigma(Ai) mod 2,L<=i<=r 尽管那个时候的可怜非常的 simple,但是她还是发现这题可以用树状数组做.当时非常yo

[CDQ分治][树状数组][树套树] Jzoj P3197 K大数查询

Description 有n 个位置和m 个操作.操作有两种,每次操作如果是1 a b c 的形式,表示往第a 个位置到第b 个位置每个位置加入一个数c.如果操作形如2 a b c 的形式,表示询问从第a 个位置到第b 个位置,第c 大的数是多少. Input 在输入文件sequence.in 中,第一行两个数n,m.意义如题目描述.接下来m 行每行形如1 a b c 或者2 a b c 如题目描述. Output 在输出文件sequence.out 中,对于每个询问回答k 大数是多少. Sam

POJ 1804 Brainman(5种解法,好题,【暴力】,【归并排序】,【线段树单点更新】,【树状数组】,【平衡树】)

Brainman Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 10575   Accepted: 5489 Description BackgroundRaymond Babbitt drives his brother Charlie mad. Recently Raymond counted 246 toothpicks spilled all over the floor in an instant just b

【数据结构之树状数组】从零认识树状数组

一.关于树状数组 树状数组(Binary Indexed Tree,简称BIT),是一种修改和查询复杂度都为O(logN)的数据结构.但树状数组仅支持单点修改,在查询时,树状数组也要求被查询的区间具有可区间加减的性质.不过,树状数组由于代码实现容易.占用空间小,常用于代替线段树. 二.详解树状数组 在这里,我们定义原序列为a,树状数组为c,则有: 其中,k为i的二进制表示中末尾0的个数,例如:i=3(101)时,k=0:i=8(1000)时,k=3. 定义函数lowbit(x)=2k(k为x的二

POJ 2299 Ultra-QuickSort (树状数组+离散化 求逆序数)

In this problem, you have to analyze a particular sorting algorithm. The algorithm processes a sequence of n distinct integers by swapping two adjacent sequence elements until the sequence is sorted in ascending order. For the input sequence 9 1 0 5

树状数组与线段树

一:树状数组 树状数组是对一个数组改变某个元素和求和比较实用的数据结构.两中操作都是O(logn). 需求:有时候我们需要频繁地求数组的前k项和或者求数组从小标i到j的和,这样每次最坏情况下的时间复杂度就会为O(N),这样效率太低了.而树状数组主要就是为了解决这样一个问题.树状数组在求和及修改都可以在O(lgN)时间内完成. 树状数组需要额外维护一个数组,我们设为C[N],原数组为A[N], 其中每个元素C[i]表示A[i-2^k+1]到A[i]的和,这里k是i在二进制时末尾0的个数.注意通过位

POJ 3928 Ping pong 树状数组模板题

开始用瓜神说的方法撸了一发线段树,早上没事闲的看了一下树状数组的方法,于是又写了一发树状数组 树状数组: #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <climits> #include <string> #include <iostream> #include <map> #includ

树状数组学习资料1

1 一维树状数组 1 什么是树状数组 树状数组是一个查询和修改复杂度都为log(n)的数据结构,假设数组A[1..n],那么查询A[1]+...+A[n]的时,间是log级别的,而且是一个在线的数据结构. 2 树状数组作用 我们经常会遇到动态连续和查询问题,给定n个元素A[1~N],让我们求sum[L,R] = A[L]+...+A[R],或者更改A[i]的值. 假设数据很小的时候,那么我们利用暴力就可以搞定,这个时候更改A[i]的复杂度为O(1),但是求和的复杂度为O(n),如果有m次求和就是

敌兵布阵(树状数组)

http://acm.hdu.edu.cn/showproblem.php?pid=1166 敌兵布阵 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 57604    Accepted Submission(s): 24347 Problem Description C国的死对头A国这段时间正在进行军事演习,所以C国间谍头子Derek和