1. 程式人生 > >關於樹刨的一些題集

關於樹刨的一些題集

getch tar head 記得 cst esp ins etc space

[ZJOI2008]樹的統計

很裸的一道樹刨題,主要是線段樹維護一下最大值即可

直接上代碼了,這道題我沒怎麽刻意去卡常數,最慢的一個998ms很神奇吧

#include<bits/stdc++.h>
#define ls(x) x<<1
#define rs(x) x<<1|1
const int INF=-2146183647;
using namespace std;
const int N=1e6+6;
int m,n,k,p,tot,cnt,res,root,inc;
int son[N],size[N],id[N],sum[N<<2
],maxx[N<<2],fa[N],head[N],dep[N],top[N],vt[N],v[N]; struct egde { int nx,to; } e[N]; void add_edge(int a,int b) { cnt++;e[cnt].to=b;e[cnt].nx=head[a];head[a]=cnt; cnt++;e[cnt].to=a;e[cnt].nx=head[b];head[b]=cnt; } void push_up(int p) { sum[p]=sum[ls(p)]+sum[rs(p)]; maxx[p]
=max(maxx[ls(p)],maxx[rs(p)]); } void build(int p,int l,int r) { if (l==r) { sum[p]=vt[l]; maxx[p]=vt[l]; return; } int mid=(l+r)>>1; build(ls(p),l,mid); build(rs(p),mid+1,r); push_up(p); } void update(int p,int l,int r,int pos,int
val) { if (l==r&&l==pos) { sum[p]=val; maxx[p]=val; return; } int mid=(l+r)>>1; if (pos<=mid) update(ls(p),l,mid,pos,val); if (pos>mid) update(rs(p),mid+1,r,pos,val); push_up(p); } void qx(int p,int l,int r,int nl,int nr) { if (nl<=l&&r<=nr) { res=max(res,maxx[p]); return; } int mid=(l+r)>>1; if (nl<=mid) qx(ls(p),l,mid,nl,nr); if (nr>mid) qx(rs(p),mid+1,r,nl,nr); } void query(int p,int l,int r,int xl,int xr) { if (xl<=l&&r<=xr) { res+=sum[p]; return; } int mid=(l+r)>>1; if (xl<=mid) query(ls(p),l,mid,xl,xr); if (xr>mid) query(rs(p),mid+1,r,xl,xr); } void dfs1(int x,int f,int deep) { fa[x]=f; dep[x]=deep; size[x]=1; int maxson=-1; for (int i=head[x];i;i=e[i].nx) { int y=e[i].to; if (y==fa[x]) continue; dfs1(y,x,deep+1); size[x]+=size[y]; if (size[y]>maxson) {maxson=size[y];son[x]=y;} } } void dfs2(int x,int topf) { id[x]=++tot; vt[tot]=v[x]; top[x]=topf; if (!son[x]) return; dfs2(son[x],topf); for (int i=head[x];i;i=e[i].nx) { int y=e[i].to; if (y==fa[x]||y==son[x]) continue; dfs2(y,y); } } int qrange(int x,int y) { int ans=0; while (top[x]!=top[y]) { res=0; if (dep[top[x]]<dep[top[y]]) swap(x,y); query(1,1,n,id[top[x]],id[x]); ans+=res; x=fa[top[x]]; } if (dep[x]>dep[y]) swap(x,y); res=0; query(1,1,n,id[x],id[y]); ans+=res; return ans; } int qmax(int x,int y) { int ans=INF; while (top[x]!=top[y]) { res=INF; if (dep[top[x]]<dep[top[y]]) swap(x,y); qx(1,1,n,id[top[x]],id[x]); ans=max(ans,res); x=fa[top[x]]; } if (dep[x]>dep[y]) swap(x,y); res=INF; qx(1,1,n,id[x],id[y]); ans=max(ans,res); return ans; } int main() { scanf("%d",&n); for (int i=1;i<n;i++) { int x,y; scanf("%d%d",&x,&y); add_edge(x,y); } for (int i=1;i<=n;i++) scanf("%d",&v[i]); root=1; dfs1(root,0,1); dfs2(root,root); build(1,1,n); scanf("%d",&m); string c; for (int i=1;i<=m;i++) { cin>>c;int x,y; scanf("%d%d",&x,&y); if (c=="QMAX") {printf("%d\n",qmax(x,y));} if (c=="QSUM") {printf("%d\n",qrange(x,y));} if (c=="CHANGE") {update(1,1,n,id[x],y);} } return 0; }

[NOI2015]軟件包管理器

其實也算是個板子吧,思想還是很好的

一開始真的沒什麽思路,然後想了想要是這個軟件已經裝上了就設成1,不然設成0,

查詢的話直接做點到根節點的權值和就好了,要是卸載了,就查詢這個點為為根節點的權值和,然後用子樹大小減去上面的權值和就好了

區間覆蓋的話將lazytag改動一下就好了

#include<bits/stdc++.h>
#define ls(x) x<<1
#define rs(x) x<<1|1
using namespace std;
const int N=4e5+6;
int m,n,k,p,l,cnt,tot,res,root;
int lg[N],sum[N],son[N],fa[N],dep[N],top[N],head[N],size[N],id[N];
struct edge
{
    int nx,to;
} e[N];
void add_edge(int a,int b)
{
    cnt++;e[cnt].to=b;e[cnt].nx=head[a];head[a]=cnt;
    cnt++;e[cnt].to=a;e[cnt].nx=head[b];head[b]=cnt;
}
void push_up(int p)
{
    sum[p]=sum[ls(p)]+sum[rs(p)];
}
void build(int p,int l,int r)
{
    lg[p]=-1;
    if (l==r) 
    {
        sum[p]=1;
        return;
    }
    int mid=(l+r)>>1;
    build(ls(p),l,mid);
    build(rs(p),mid+1,r);
    push_up(p);
}
void push_down(int p,int lenn)
{
    if (lg[p]==-1) return;
    lg[ls(p)]=lg[p];
    lg[rs(p)]=lg[p];
    sum[ls(p)]=lg[p]*(lenn-(lenn>>1));
    sum[rs(p)]=lg[p]*(lenn>>1);
    lg[p]=-1;
}
void update(int p,int l,int r,int nl,int nr,int k)
{
    if (nl<=l&&r<=nr)
    {
        sum[p]=(r-l+1)*k;
        lg[p]=k;
        return;
    }
    push_down(p,(r-l+1));
    int mid=(l+r)>>1;
    if (nl<=mid) update(ls(p),l,mid,nl,nr,k);
    if (nr>mid) update(rs(p),mid+1,r,nl,nr,k);
    push_up(p);
}
void query(int p,int l,int r,int xl,int xr)
{
    if (xl<=l&&r<=xr) 
    {
        res+=sum[p];
        return;
    }
    push_down(p,(r-l+1));
    int mid=(l+r)>>1;
    if (xl<=mid) query(ls(p),l,mid,xl,xr);
    if (xr>mid) query(rs(p),mid+1,r,xl,xr);
}
void dfs1(int x,int f,int deep)
{
    dep[x]=deep;
    fa[x]=f;
    size[x]=1;
    int maxson=-1;
    for (int i=head[x];i;i=e[i].nx)
    {
        int y=e[i].to;
        if (y==fa[x]) continue;
        dfs1(y,x,deep+1);
        size[x]+=size[y];
        if (size[y]>maxson) {son[x]=y;maxson=size[y];}
    }
}
void dfs2(int x,int topf)
{
    id[x]=++tot;
    top[x]=topf;
    if (!son[x]) return;
    dfs2(son[x],topf);
    for (int i=head[x];i;i=e[i].nx)
    {
        int y=e[i].to;
        if (y==fa[x]||y==son[x]) continue;
        dfs2(y,y);
    }
}
int queson(int x)
{
    int ans=0;
    res=0;
    query(1,1,n,id[x],id[x]+size[x]-1);
    ans=res;
    return ans;
}
int querange(int x,int y)
{
    int ans=0;
    while (top[x]!=top[y])
    {
        if(dep[top[x]]<dep[top[y]]) swap(x,y);
        res=0;
        query(1,1,n,id[top[x]],id[x]);
        ans+=res;
        x=fa[top[x]];
    }
    if (dep[x]>dep[y]) swap(x,y);
    res=0;
    query(1,1,n,id[x],id[y]);
    ans+=res;
    return ans;
}
void uprange(int x,int y,int k)
{
    while (top[x]!=top[y])
    {
        if (dep[top[x]]<dep[top[y]]) swap(x,y);
        update(1,1,n,id[top[x]],id[x],k);
        x=fa[top[x]];
    }
    if (dep[x]>dep[y]) swap(x,y);
    update(1,1,n,id[x],id[y],k);
}
int main()
{
    scanf("%d",&n);
    root=1;
    for (int i=1;i<=n-1;i++) 
    {
        int x; scanf("%d",&x);
        x++;
        add_edge(x,i+1);
    }
    dfs1(root,0,1);
    dfs2(root,root);
    build(1,1,n);
    scanf("%d",&m);
    string s;int x;
    for (int i=1;i<=m;i++)
    {
        cin>>s;
        scanf("%d",&x);
        x++;
        if (s=="install") {printf("%d\n",querange(x,root));uprange(x,root,0);}
        if (s=="uninstall") {printf("%d\n",size[x]-queson(x));update(1,1,n,id[x],id[x]+size[x]-1,1);}
    }
    return 0;
}

[HAOI2015]樹上操作

這道題就教會了我一點,記得開longlong

#include<cstring>
#include<cstdio>
#include<algorithm>
#define ls(x) x<<1
#define rs(x) x<<1|1
#define ll long long
using namespace std;
const int N=4e5+6;
ll res,ans;
ll cnt,tot,m,n,root;
ll sum[N],lg[N];
ll size[N],top[N],v[N],vt[N],fa[N],head[N],dep[N],id[N],son[N];
struct edge
{
    ll nx,to;
} e[N];
void add_edge(ll a,ll b)
{
    cnt++;e[cnt].nx=head[a];e[cnt].to=b;head[a]=cnt;
    cnt++;e[cnt].nx=head[b];e[cnt].to=a;head[b]=cnt;
}
void push_up(ll p)
{
    sum[p]=sum[ls(p)]+sum[rs(p)];
}
void build(ll p,ll l,ll r)
{
    if (l==r) 
    {
        sum[p]=(ll)vt[l];
        return;
    }
    ll mid=(l+r)>>1;
    build(ls(p),l,mid);
    build(rs(p),mid+1,r);
    push_up(p);
}
void push_down(ll p,ll lenn)
{
    lg[ls(p)]+=lg[p];
    lg[rs(p)]+=lg[p];
    sum[ls(p)]+=lg[p]*(lenn-(lenn>>1));
    sum[rs(p)]+=lg[p]*(lenn>>1);
    lg[p]=0;
}
void update(ll p,ll l,ll r,ll nl,ll nr,ll k)
{
    if (nl<=l&&r<=nr)
    {
        lg[p]+=k;
        sum[p]+=k*(r-l+1);
        return;
    }
    ll mid=(l+r)>>1;
    push_down(p,(r-l+1));
    if (nl<=mid) update(ls(p),l,mid,nl,nr,k);
    if (nr>mid) update(rs(p),mid+1,r,nl,nr,k);
    push_up(p);
}
void query(ll p,ll l,ll r,ll xl,ll xr)
{
    if (xl<=l&&r<=xr) 
    {
        res+=sum[p];
        return;
    }
    push_down(p,(r-l+1));
    ll mid=(l+r)>>1;
    if (xl<=mid) query(ls(p),l,mid,xl,xr);
    if (xr>mid) query(rs(p),mid+1,r,xl,xr);
}
void dfs1(ll x,ll f,ll deep)
{
    dep[x]=deep;
    fa[x]=f;
    size[x]=1;
    ll maxson=-1;
    for (ll i=head[x];i;i=e[i].nx)
    {
        ll y=e[i].to;
        if (y==fa[x]) continue;
        dfs1(y,x,deep+1);
        size[x]+=size[y];
        if (size[y]>maxson) {son[x]=y;maxson=size[y];}
    }
}
void dfs2(ll x,ll topf)
{
    id[x]=++tot;
    vt[tot]=v[x];
    top[x]=topf;
    if (!son[x]) return;
    dfs2(son[x],topf);
    for (ll i=head[x];i;i=e[i].nx)
    {
        ll y=e[i].to;
        if (y==fa[x]||y==son[x]) continue;
        dfs2(y,y);
    }
}
void uprange(ll x,ll y,ll k)
{
    while (top[x]!=top[y])
    {
        if (dep[top[x]]<dep[top[y]]) swap(x,y);
        update(1,1,n,id[top[x]],id[x],k);
        x=fa[top[x]];
    }
    if (dep[x]>dep[y]) swap(x,y);
    update(1,1,n,id[x],id[y],k);
}
void upson(ll x,ll y)
{
    update(1,1,n,id[x],id[x]+size[x]-1,y);
}
ll querange(ll x,ll y)
{
    ll ans=0;
    while(top[x]!=top[y])
    {
        if (dep[top[x]]<dep[top[y]]) swap(x,y);
        res=0;
        query(1,1,n,id[top[x]],id[x]);
        ans+=res;
        x=fa[top[x]];
    }
    if (dep[x]>dep[y]) swap(x,y);
    res=0;
    query(1,1,n,id[x],id[y]);
    ans+=res;
    return ans;
}
int main()
{
    scanf("%lld%lld",&n,&m);
    for (ll i=1;i<=n;i++) scanf("%lld",&v[i]);
    for (ll i=1;i<n;i++)
    {
        ll x,y;
        scanf("%lld%lld",&x,&y);
        add_edge(x,y);
    }
    root=1;
    dfs1(root,0,1);
    dfs2(root,root);
    build(1,1,n);
    for (ll i=1;i<=m;i++)
    {
        ll opt,x,y;
        scanf("%lld",&opt);
        if (opt==1) {scanf("%lld%lld",&x,&y);uprange(x,x,y);}
        if (opt==2) {scanf("%lld%lld",&x,&y);upson(x,y);}
        if (opt==3) {scanf("%lld",&x);printf("%lld\n",querange(x,root));}
    }
    return 0;
} 

[JLOI2014]松鼠的新家

裸題,沒啥好說的放在最後啦

#include<bits/stdc++.h>
#define ls(x) x<<1
#define rs(x) x<<1|1
using namespace std;
const int N=12e5+6;
int m,n,k,l,root,res,cnt,tot,from,to;
int size[N],top[N],v[N],vt[N],fa[N],sum[N<<2],lg[N<<2],head[N],dep[N],id[N],son[N];
int a[N];
int read()
{
    int x=0,f=1;char ch=getchar();
    while (ch<0||ch>9) {if (ch==-) f=-1;ch=getchar();}
    while (ch>=0&&ch<=9) {x=x*10+ch-0;ch=getchar();}
    return x*f;
}
struct edge
{
    int nx,to;
} e[N];
void add_edge(int a,int b)
{
    cnt++;e[cnt].nx=head[a];e[cnt].to=b;head[a]=cnt;
    cnt++;e[cnt].nx=head[b];e[cnt].to=a;head[b]=cnt;
}
void push_up(int p)
{
    sum[p]=sum[ls(p)]+sum[rs(p)];
}
void build(int p,int l,int r)
{
    if (l==r) 
    {
        sum[p]=vt[l];
        return;
    }
    int mid=(l+r)>>1;
    build(ls(p),l,mid);
    build(rs(p),mid+1,r);
    push_up(p);
}
void push_down(int p,int lenn)
{
    lg[ls(p)]+=lg[p];
    lg[rs(p)]+=lg[p];
    sum[ls(p)]+=lg[p]*(lenn-(lenn>>1));
    sum[rs(p)]+=lg[p]*(lenn>>1);
    lg[p]=0;
}
void update(int p,int l,int r,int nl,int nr,int k)
{
    if (nl<=l&&r<=nr)
    {
        lg[p]+=k;
        sum[p]+=k*(r-l+1);
        return;
    }
    int mid=(l+r)>>1;
    push_down(p,(r-l+1));
    if (nl<=mid) update(ls(p),l,mid,nl,nr,k);
    if (nr>mid) update(rs(p),mid+1,r,nl,nr,k);
    push_up(p);
}
void del(int p,int l,int r,int pos)
{
    if (l==r&&r==pos) {sum[p]--;return;}
    int mid=(l+r)>>1;
    if (pos<=mid) del(ls(p),l,mid,pos); 
    if (pos>mid) del(rs(p),mid+1,r,pos);
}
void query(int p,int l,int r,int xl,int xr)
{
    if (xl<=l&&r<=xr) 
    {
        res+=sum[p];
        return;
    }
    push_down(p,(r-l+1));
    int mid=(l+r)>>1;
    if (xl<=mid) query(ls(p),l,mid,xl,xr);
    if (xr>mid) query(rs(p),mid+1,r,xl,xr);
}
void dfs1(int x,int f,int deep)
{
    dep[x]=deep;
    fa[x]=f;
    size[x]=1;
    int maxson=-1;
    for (int i=head[x];i;i=e[i].nx)
    {
        int y=e[i].to;
        if (y==fa[x]) continue;
        dfs1(y,x,deep+1);
        size[x]+=size[y];
        if (size[y]>maxson) {son[x]=y;maxson=size[y];}
    }
}
void dfs2(int x,int topf)
{
    id[x]=++tot;
    vt[tot]=v[x];
    top[x]=topf;
    if (!son[x]) return;
    dfs2(son[x],topf);
    for (int i=head[x];i;i=e[i].nx)
    {
        int y=e[i].to;
        if (y==fa[x]||y==son[x]) continue;
        dfs2(y,y);
    }
}
void uprange(int x,int y)
{
    while (top[x]!=top[y])
    {
        if (dep[top[x]]<dep[top[y]]) swap(x,y);
        update(1,1,n,id[top[x]],id[x],1);
        x=fa[top[x]];
    }
    if (dep[x]>dep[y]) swap(x,y);
    update(1,1,n,id[x],id[y],1);
}
int main()
{
    n=read();
    for (int i=1;i<=n;i++) a[i]=read();
    for (int i=1;i<n;i++)
    {
        int x,y;
        x=read();y=read();
        add_edge(x,y);
    }
    root=a[1];
    dfs1(root,0,1);
    dfs2(root,root);
    build(1,1,n);
    for (int i=1;i<=n-1;i++)
    {
        uprange(a[i],a[i+1]);
    }
    for (int i=2;i<=n;i++)
    update(1,1,n,id[a[i]],id[a[i]],-1);
    for (int i=1;i<=n;i++)
    {
      res=0;
      query(1,1,n,id[i],id[i]);
      printf("%d\n",res);
    }
    return 0;
}

hale 加油啊

關於樹刨的一些題集