hdu5029 Relief grain 点权树链剖分,线段树

点权树链剖分,求出所有更改区间,用一个类似差分前缀和的东西扫一遍。

点权与边权的剖分在查询上有一点小区别。

#pragma comment(linker,"/STACK:1024000000,1024000000")
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define fi first
#define se second
#define pii pair
#define ll long long
#define inf 1<<30
#define eps 1e-8
using namespace std;
const int maxn=100005;
int son[maxn],top[maxn],dep[maxn],fa[maxn],siz[maxn],id[maxn],fid[maxn];
int sz;
vectorg[maxn];
int n,m;
vectorzh[maxn];
vectorfu[maxn];
int ans[maxn];
pii tree[maxn<<2];
int N=100000;
void dfs(int u,int f)
{
    siz[u]=1;
    son[u]=0;
    for(int i=0;isiz[son[u]]) son[u]=v;
        siz[u]+=siz[v];
    }
}
void build(int u,int w)
{
    id[u]=++sz;
    fid[sz]=u;
    top[u]=w;
    if(son[u]) build(son[u],w);
    for(int i=0;idep[b]) swap(a,b);
    zh[id[a]].push_back(c);
    fu[id[b]+1].push_back(c);
}
void pushUp(int rt)
{
    if(tree[rt<<1].fi>=tree[rt<<1|1].fi)
        tree[rt]=tree[rt<<1];
    else
        tree[rt]=tree[rt<<1|1];
}
void buildTree(int l,int r,int rt)
{
    if(l==r) {
        tree[rt].fi=0;
        tree[rt].se=0;
        return;
    }
    int m=(l+r)/2;
    buildTree(l,m,rt<<1);
    buildTree(m+1,r,rt<<1|1);
    pushUp(rt);
}
void update(int L,int a,int l,int r,int rt)
{
    if(L==l && L==r) {
        tree[rt].fi+=a;
        if(tree[rt].fi>0)
            tree[rt].se=l;
        else
            tree[rt].se=0;
        return;
    }
    int m=(l+r)/2;
    if(L<=m)
        update(L,a,l,m,rt<<1);
    else
        update(L,a,m+1,r,rt<<1|1);
    pushUp(rt);
}
int main()
{
    int a,b,c;
    while(~scanf("%d%d",&n,&m)) {
        if(n==0 && m==0) break;
        for(int i=1;i<=n;i++) {
            g[i].clear();
            zh[i].clear();
            fu[i].clear();
        }
        for(int i=0;i


你可能感兴趣的:(树链剖分)