洛谷试炼场 4-17 树链剖分


layout: post
title: 洛谷试炼场 4-17 树链剖分
author: "luowentaoaa"
catalog: true
mathjax: true
tags:
- 树链剖分
- 数据结构
- 洛谷


[ZJOI2008]树的统计 (入门题,链最大值,链和)

思路

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=998244353;
const int maxn=1e6+50;
const ll inf=0x3f3f3f3f3f3f3f3fLL;
int n,q,a[maxn];
vector<int>G[maxn];
int size[maxn],son[maxn],fa[maxn],dep[maxn],top[maxn];
int id[maxn],pre[maxn],cnt=0;
void dfs1(int u,int f,int deep){
    size[u]=1;
    fa[u]=f;son[u]=0;dep[u]=deep;
    for(int i=0;i<G[u].size();i++){
        int v=G[u][i];
        if(v==f)continue;
        dfs1(v,u,deep+1);
        size[u]+=size[v];
        if(size[v]>size[son[u]])son[u]=v;
    }
}
void dfs2(int u,int root){
    id[u]=++cnt;top[u]=root;pre[cnt]=u;
    if(son[u])dfs2(son[u],root);
    for(int i=0;i<G[u].size();i++){
        int v=G[u][i];
        if(v==fa[u]||v==son[u])continue;
        dfs2(v,v);
    }
}
int sumv[maxn<<2],maxv[maxn<<2];
inline void pushup(int o){
    sumv[o]=sumv[o<<1]+sumv[o<<1|1];
    maxv[o]=max(maxv[o<<1],maxv[o<<1|1]);
}
void build(int o,int l,int r){
    int mid=(l+r)/2;
    if(l==r){
        sumv[o]=maxv[o]=a[pre[l]];return;
    }
    build(o<<1,l,mid);build(o<<1|1,mid+1,r);
    pushup(o);
}
void update(int o,int l,int r,int q,int v){
    int mid=(l+r)/2;
    if(l==r){
        sumv[o]=maxv[o]=v;return;
    }
    if(q<=mid)update(o<<1,l,mid,q,v);
    else update(o<<1|1,mid+1,r,q,v);
    pushup(o);
}
int querysum(int o,int l,int r,int ql,int qr){
    int mid=(l+r)/2,ans=0;
    if(ql<=l&&r<=qr)return sumv[o];
    if(ql<=mid)ans+=querysum(o<<1,l,mid,ql,qr);
    if(qr>mid)ans+=querysum(o<<1|1,mid+1,r,ql,qr);
    return ans;
}
int querymax(int o,int l,int r,int ql,int qr){
    int mid=(l+r)/2,ans=-inf;
    if(ql<=l&&r<=qr)return maxv[o];
    if(ql<=mid)ans=max(ans,querymax(o<<1,l,mid,ql,qr));
    if(qr>mid)ans=max(ans,querymax(o<<1|1,mid+1,r,ql,qr));
    return ans;
}
int qsum(int u,int v){
    int ans=0;
    while(top[u]!=top[v]){
        if(dep[top[u]]<dep[top[v]])swap(u,v);
        ans+=querysum(1,1,n,id[top[u]],id[u]);
        u=fa[top[u]];
    }
    if(dep[u]<dep[v])swap(u,v);
    ans+=querysum(1,1,n,id[v],id[u]);
    return ans;
}
int qmax(int u,int v){
    int ans=-inf;
    while(top[u]!=top[v]){
        if(dep[top[u]]<dep[top[v]])swap(u,v);
        ans=max(ans,querymax(1,1,n,id[top[u]],id[u]));
        u=fa[top[u]];
    }
    if(dep[u]<dep[v])swap(u,v);
    ans=max(ans,querymax(1,1,n,id[v],id[u]));
    return ans;
}
int main()
{
    std::ios::sync_with_stdio(false);
    std::cin.tie(0);
    std::cout.tie(0);
    cin>>n;
    for(int i=1;i<n;i++){
        int u,v;
        cin>>u>>v;G[u].push_back(v);G[v].push_back(u);
    }
    for(int i=1;i<=n;i++)cin>>a[i];
    fa[1]=1;dfs1(1,0,1);dfs2(1,1);build(1,1,n);
    int q;
    cin>>q;
    while(q--){
        int x,y;char s[100];
        cin>>s>>x>>y;
        if(s[1]=='H')update(1,1,n,id[x],y);
        else if(s[1]=='M')cout<<qmax(x,y)<<endl;
        else if(s[1]=='S')cout<<qsum(x,y)<<endl;
    }
    return 0;
}

[P2486 SDOI2011]染色 (区间操作很难 未AC)

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=998244353;
const int maxn=1e6+50;
const ll inf=0x3f3f3f3f3f3f3f3fLL;
int n,q,col[maxn];
vector<int>G[maxn];
int size[maxn],son[maxn],fa[maxn],dep[maxn],top[maxn];
int id[maxn],pre[maxn],cnt=0;
void dfs1(int u,int f,int deep){
    size[u]=1;
    fa[u]=f;son[u]=0;dep[u]=deep;
    for(int i=0;i<G[u].size();i++){
        int v=G[u][i];
        if(v==f)continue;
        dfs1(v,u,deep+1);
        size[u]+=size[v];
        if(size[v]>size[son[u]])son[u]=v;
    }
}
void dfs2(int u,int root){
    id[u]=++cnt;top[u]=root;pre[cnt]=u;
    if(son[u])dfs2(son[u],root);
    for(int i=0;i<G[u].size();i++){
        int v=G[u][i];
        if(v==fa[u]||v==son[u])continue;
        dfs2(v,v);
    }
}
struct node{
    int l,r;
    int num,lazy,lc,rc;
}my[maxn<<2];
void push_up(int o){
    my[o].lc=my[o<<1].lc;my[o].rc=my[(o<<1)|1].rc;
    int ans=my[o<<1].num+my[(o<<1)|1].num;
    if(my[o<<1].rc==my[(o<<1)|1].lc)ans--;
    my[o].num=ans;
}
void push_down(int o){
    if(my[o].lazy){
        my[o<<1].lazy=my[(o<<1)|1].lazy=my[o].lazy;
        my[o<<1].num=my[(o<<1)|1].num=1;
        my[o<<1].lc=my[o<<1].rc=my[o].lc;
        my[(o<<1)|1].lc=my[(o<<1)|1].rc=my[o].lc;
        my[o<<1].lazy=0;
    }
}
void build(int o,int l,int r){
    int mid=(l+r)/2;
    my[o].l=l;my[o].r=r;my[o].num=0;my[o].lazy=0;
    if(l==r){
        my[o].num=1;
        my[o].lc=my[o].rc=col[pre[l]];
        return;
    }
    build(o<<1,l,mid);build((o<<1)|1,mid+1,r);
    push_up(o);
}
void update(int o,int l,int r,int x){
    if(my[o].l==l&&my[o].r==r){
        my[o].num=my[o].lazy=1;
        my[o].lc=my[o].rc=x;
        return;
    }
    push_down(o);
    int mid=(my[o].l+my[o].r)/2;
    if(r<=mid)update(o<<1,l,r,x);
    else if(l>mid)update((o<<1)|1,l,r,x);
    else{
        update(o<<1,l,mid,x);update((o<<1)|1,mid+1,r,x);
    }
    push_up(o);
}
void uptree(int u,int v,int c){
    while(top[u]!=top[v]){
        if(dep[top[u]]<dep[top[v]])swap(u,v);
        update(1,id[top[u]],id[u],c);
        u=fa[top[u]];
    }
    if(dep[u]<dep[v])swap(u,v);
    update(1,id[v],id[u],c);
}
int lc,rc;
int query(int o,int l,int r,int L,int R){
    if(my[o].l==L)lc=my[o].lc;
    if(my[o].r==R)rc=my[o].rc;
    if(my[o].l==l&&my[o].r==r)return my[o].num;
    push_down(o);
    int mid=(my[o].l+my[o].r)/2;
    if(r<=mid)return query(o<<1,l,r,L,R);
    else if(l>mid)return query((o<<1)|1,l,r,L,R);
    else{
        int ans=query(o<<1,l,mid,L,R);
        ans+=query((o<<1)|1,mid+1,r,L,R);
        if(my[o<<1].rc==my[(o<<1)|1].lc)ans--;
        return ans;
    }
    push_up(o);
}
int qutree(int u,int v){
    int ans1=-1,ans2=-1,ans=0;
    while(top[u]!=top[v]){
        if(dep[top[u]]<dep[top[v]])swap(u,v),swap(ans1,ans2);
        ans+=query(1,id[top[u]],id[u],id[top[u]],id[u]);
        if(rc==ans1)ans--;
        ans1=lc;u=fa[top[u]];
    }
    if(dep[u]<dep[v])swap(u,v),swap(ans1,ans2);
    ans+=query(1,id[v],id[u],id[v],id[u]);
    if(rc==ans1)ans--;
    if(lc==ans2)ans--;
    return ans;
}
int main()
{
    std::ios::sync_with_stdio(false);
    std::cin.tie(0);
    std::cout.tie(0);
    int m;
    cin>>n>>m;
    for(int i=1;i<=n;i++)cin>>col[i];
    for(int i=1;i<n;i++){
        int u,v;cin>>u>>v;
        G[u].push_back(v);G[v].push_back(u);
    }
    dfs1(1,1,1);dfs2(1,1);build(1,1,n);
    while(m--){
        char s[150];
        cin>>s;
        int x,y;
        if(s[0]=='C'){
            int c;cin>>x>>y>>c;
            uptree(x,y,c);
        }
        else{
            cin>>x>>y;
            cout<<qutree(x,y)<<endl;
        }
    }
    return 0;
}

[P2146 NOI2015]软件包管理器

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=998244353;
const int maxn=1e6+50;
const ll inf=0x3f3f3f3f3f3f3f3fLL;
int n,q,col[maxn];
vector<int>G[maxn];
int size[maxn],son[maxn],fa[maxn],dep[maxn],top[maxn];
int id[maxn],pre[maxn],cnt=0;
void dfs1(int u,int f,int deep){
    size[u]=1;
    fa[u]=f;son[u]=0;dep[u]=deep;
    for(int i=0;i<G[u].size();i++){
        int v=G[u][i];
        if(v==f)continue;
        dfs1(v,u,deep+1);
        size[u]+=size[v];
        if(size[v]>size[son[u]])son[u]=v;
    }
}
void dfs2(int u,int root){
    id[u]=++cnt;top[u]=root;pre[cnt]=u;
    if(son[u])dfs2(son[u],root);
    for(int i=0;i<G[u].size();i++){
        int v=G[u][i];
        if(v==fa[u]||v==son[u])continue;
        dfs2(v,v);
    }
}
int sum[maxn<<2],lazy[maxn<<2];
void push_up(int o){
    sum[o]=sum[o<<1]+sum[o<<1|1];
}
void push_down(int o,int l,int r){
    if(lazy[o]){
        int mid=(l+r)/2;
        if(lazy[o]==-1)sum[o<<1]=sum[o<<1|1]=0,lazy[o<<1]=lazy[o<<1|1]=-1;
        else sum[o<<1]=mid-l+1,sum[o<<1|1]=r-mid,lazy[o<<1]=lazy[o<<1|1]=1;
        lazy[o]=0;
    }
}
void uninstall(int o,int l,int r,int ql,int qr,int x){
    if(ql<=l&&r<=qr){
        if(!x)lazy[o]=-1,sum[o]=0;
        else lazy[o]=1,sum[o]=r-l+1;return;
    }
    int mid=(l+r)/2;push_down(o,l,r);
    if(mid>=ql)uninstall(o<<1,l,mid,ql,qr,x);
    if(mid<qr)uninstall(o<<1|1,mid+1,r,ql,qr,x);
    push_up(o);
}
void install(int v,int x,int y){
    while(top[x]!=top[y]){
        if(dep[top[x]]<dep[top[y]])swap(x,y);
        uninstall(1,1,n,id[top[x]],id[x],v);
        x=fa[top[x]];
    }
    if(dep[x]<dep[y])swap(x,y);
    uninstall(1,1,n,id[y],id[x],v);
}

int main()
{
    std::ios::sync_with_stdio(false);
    std::cin.tie(0);
    std::cout.tie(0);
    cin>>n;
    for(int i=2;i<=n;i++){
        int u;
        cin>>u;u++;
        G[i].push_back(u);
        G[u].push_back(i);
    }
    dfs1(1,1,1);
    dfs2(1,1);
    int m;cin>>m;
    char op[150];
    while(m--){
        int x;
        cin>>op>>x;x++;int p=sum[1];
        if(op[0]=='i'){
            install(1,x,1);
            cout<<abs(p-sum[1])<<endl;
        }
        else{
            uninstall(1,1,n,id[x],id[x]+size[x]-1,0);
            cout<<abs(p-sum[1])<<endl;
        }
    }
    return 0;
}
/*
7
0 0 0 1 1 5
5
install 5
install 6
uninstall 1
install 4
uninstall 0
*/

[P3258 JLOI2014]松鼠的新家 (区间加减)

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=998244353;
const int maxn=3e5+50;
const ll inf=0x3f3f3f3f3f3f3f3fLL;
vector<int>G[maxn];
int id[maxn],dep[maxn],pre[maxn],fa[maxn],size[maxn],son[maxn],cnt,top[maxn];
void dfs1(int now,int f,int deep){
    fa[now]=f;size[now]=1;son[now]=0;dep[now]=deep;
    for(auto i:G[now]){
        if(i==f)continue;
        dfs1(i,now,deep+1);
        size[now]+=size[i];
        if(size[i]>size[son[now]])son[now]=i;
    }
}
void dfs2(int now,int root){
    id[now]=++cnt;pre[cnt]=now;top[now]=root;
    if(son[now])dfs2(son[now],root);
    for(auto i:G[now]){
        if(i==fa[now]||i==son[now])continue;
        dfs2(i,i);
    }
}
int sum[maxn<<2],lazy[maxn<<2];
void push_up(int o){
    sum[o]=sum[o<<1]+sum[o<<1|1];
}
void push_down(int o,int l,int r){
    if(lazy[o]){
        int mid=(l+r)/2;
        lazy[o<<1]+=lazy[o];
        lazy[o<<1|1]+=lazy[o];
        sum[o<<1]+=(mid-l+1)*lazy[o];
        sum[o<<1|1]+=(r-mid)*lazy[o];
        lazy[o]=0;
    }
}
void update(int o,int l,int r,int ql,int qr,int w){
    int mid=(l+r)/2;
    if(ql<=l&&r<=qr){
        lazy[o]+=w;
        sum[o]+=(r-l+1)*w;
        return;
    }
    push_down(o,l,r);
    if(ql<=mid)update(o<<1,l,mid,ql,qr,w);
    if(qr>mid)update(o<<1|1,mid+1,r,ql,qr,w);
    push_up(o);
}
void print(int o,int l,int r,int ql,int qr){
    cout<<"o=="<<o<<" l="<<l<<" r="<<r<<" ql="<<ql<<" qr="<<qr<<endl;
    cout<<"sum="<<sum[o]<<endl;
}
int query(int o,int l,int r,int ql,int qr){
    //print(o,l,r,ql,qr);
    if(l==r){
        return sum[o];
    }
    int mid=(l+r)/2;
    push_down(o,l,r);
    if(ql<=mid)return query(o<<1,l,mid,ql,qr);
    else return query(o<<1|1,mid+1,r,ql,qr);
}
void uptree(int u,int v,int w){
    while(top[u]!=top[v]){
        if(dep[top[u]]<dep[top[v]])swap(u,v);
        update(1,1,cnt,id[top[u]],id[u],w);
        u=fa[top[u]];
    }
    if(dep[u]<dep[v])swap(u,v);
    update(1,1,cnt,id[v],id[u],w);
}
int a[maxn];
// 适用于正负整数
template <class T>
inline bool read(T &ret)
{
    char c;
    int sgn;
    if (c = getchar(), c == EOF) return 0; //EOF
    while (c != '-' && (c < '0' || c > '9')) c = getchar();
    sgn = (c == '-') ? -1 : 1;
    ret = (c == '-') ? 0 : (c - '0');
    while (c = getchar(), c >= '0' && c <= '9') ret = ret * 10 + (c - '0');
    ret *= sgn;
    return 1;
}
inline void out(int x)
{
    if (x > 9) out(x / 10);
    putchar(x % 10 + '0');
}
int main()
{
   /* std::ios::sync_with_stdio(false);
    std::cin.tie(0);
    std::cout.tie(0);*/
    int n;
    //cin>>n;
    read(n);
    for(int i=1;i<=n;i++)cin>>a[i];
    for(int i=1;i<n;i++){
        int u,v;
       // cin>>u>>v;
        read(u);read(v);
        G[u].push_back(v);
        G[v].push_back(u);
    }
    dfs1(1,1,1);dfs2(1,1);
    for(int i=1;i<n;i++){
        uptree(a[i],a[i+1],1);
        uptree(a[i+1],a[i+1],-1);
    }
    for(int i=1;i<=n;i++){
       // cout<<query(1,1,n,id[i],id[i])<<endl;
        out(query(1,1,n,id[i],id[i]));
        puts("");
    }
    return 0;
}
原文地址:https://www.cnblogs.com/luowentao/p/10358514.html