关于树剖板子的一些憨憨错误

洛谷P2590 树的统计(https://www.luogu.org/problem/P2590)

啊调了6个小时,血的教训啊。。。在树链剖分后,由于树按照DFN序重新编号,如果要直接调用线段树操作,需要操作ID[X]而不能直接操作编号X

#include
#include
#include
#include
#include
using namespace std;
const int maxn=30030;
int head[maxn],top[maxn],dep[maxn],fa[maxn],id[maxn],sz[maxn],son[maxn];
int n,m,cnt,num,flag ,p,q,t;
int a[maxn],b[maxn];
string k;
struct pp
{
    int u;
    int nex;
}e[maxn*2];
struct kk
{
    int l,r;
    int sum,maxl;
}s[maxn*4];

void add(int x,int y)
{
    e[++cnt].u=y;
    e[cnt].nex=head[x];
    head[x]=cnt;
}
void up(int rt)
{
    s[rt].sum=s[rt<<1].sum+s[rt<<1|1].sum;
    s[rt].maxl=max(s[rt<<1].maxl,s[rt<<1|1].maxl);
}
void build(int rt,int l,int r)
{
    s[rt].l=l;
    s[rt].r=r;
    s[rt].maxl=-maxn*4;
    s[rt].sum=0;
    if(l==r)
    {
        s[rt].sum=s[rt].maxl=a[l];
        return;
    }
    int mid=(l+r)>>1;
    build(rt<<1,l,mid);
    build(rt<<1|1,mid+1,r);
    up(rt);
}
int qsum(int rt,int l,int r)
{
    if(l<=s[rt].l&&r>=s[rt].r)
     return s[rt].sum;
    int ans=0;
    int mid=(s[rt].l+s[rt].r)>>1;
    if(l<=mid) ans+=qsum(rt<<1,l,r);
    if(r>mid) ans+=qsum(rt<<1|1,l,r);
    return ans;
}
int qmax(int rt,int l,int r)
{
    if(l<=s[rt].l&&r>=s[rt].r)
     return s[rt].maxl;
    int ans=-maxn*100;
    int mid=(s[rt].l+s[rt].r)>>1;
    if(l<=mid) ans=max(ans,qmax(rt<<1,l,r));
    if(r>mid) ans=max(ans,qmax(rt<<1|1,l,r));
    return ans;
}
void modify(int rt,int x,int v)
{
    if(s[rt].l==s[rt].r&&s[rt].r==x)
    {
        s[rt].sum=s[rt].maxl=v;
        return;
    }
    int mid=(s[rt].l+s[rt].r)>>1;
    if(x<=mid) modify(rt<<1,x,v);
    else modify(rt<<1|1,x,v);
    up(rt);
}

void dfs1(int x,int f,int deep)
{
    fa[x]=f;
    dep[x]=deep;
    sz[x]=1;
    int ms=-1;
    for(int i=head[x];i;i=e[i].nex)
    {
        int y=e[i].u;
        if(y==f) continue;
        dfs1(y,x,deep+1);
        sz[x]+=sz[y];
        if(sz[y]>ms)
        {
            ms=sz[y];
            son[x]=y;
        }
    }
}

void dfs2(int x,int tt)
{
    id[x]=++num;
    a[num]=b[x];
    top[x]=tt;
    if(!son[x]) return;
    dfs2(son[x],tt);
    for(int i=head[x];i;i=e[i].nex)
    {
        int y=e[i].u;
        if(y==fa[x]||y==son[x]) continue;
        dfs2(y,y);
    }
}

int anssum(int x,int y)
{
    int ans=0;
    while(top[x]!=top[y])
    {
        if(dep[top[x]]<dep[top[y]]) swap(x,y);
        ans+=qsum(1,id[top[x]],id[x]);
        x=fa[top[x]];
    }
    if(dep[x]<dep[y]) swap(x,y);
    ans+=qsum(1,id[y],id[x]);
    return ans;
    
}

int ansmax(int x,int y)
{
    int ans=-maxn*100;
    while(top[x]!=top[y])
    {
        if(dep[top[x]]<dep[top[y]]) swap (x,y);
        ans=max(ans,qmax(1,id[top[x]],id[x]));
        x=fa[top[x]];
    }
    if(dep[x]<dep[y]) swap(x,y);
    ans=max(ans,qmax(1,id[y],id[x]));
    return ans;
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=(n-1);i++)
    {
        int aa,bb;
        scanf("%d%d",&aa,&bb);
        add(aa,bb);add(bb,aa);
    }
    for(int i=1;i<=n;i++)
     scanf("%d",&b[i]);
    dfs1(1,0,1);
    dfs2(1,1);
    build(1,1,n); 
    scanf("%d",&t);
    while(t--)
    {
        cin>>k;
        scanf("%d%d",&p,&q);
        if(k=="CHANGE")
        modify(1,id[p],q);
        else if(k=="QMAX")
        printf("%d\n",ansmax(p,q));
        else printf("%d\n",anssum(p,q));
    }
    return 0;
}
P2590

 

 

 

洛谷P3178 树上操作(https://www.luogu.org/problem/P3178)

这题莫名要用long long。。。看来是有全部点排成一条链的奇葩情况。。。

另外如果批量修改int 的话还可以用

#define int long long
signed main()
{}

省的一个个手改了

#include
#include
#include
#include
#include
using namespace std;
const int maxn=100010;
long long n,m,cnt,flag,num,res,t,p,q;
long long head[maxn],top[maxn],son[maxn],id[maxn],sz[maxn],fa[maxn],dep[maxn],a[maxn],b[maxn];
struct pp
{
    long long l,r;
     long long sum, tag;
}s[maxn*4];

struct yy
{
    long long u;
    long long nex;
}e[maxn*2];
void add(long long x,long long y)
{
    e[++cnt].u=y;
    e[cnt].nex=head[x];
    head[x]=cnt;
}
void up(long long rt)
{
    s[rt].sum=s[rt<<1].sum+s[rt<<1|1].sum;
}


void down(long long rt)
{
    if(s[rt].tag)
    {
        s[rt<<1].sum=(s[rt<<1].sum+s[rt].tag*(s[rt<<1].r-s[rt<<1].l+1));
        s[rt<<1|1].sum=(s[rt<<1|1].sum+s[rt].tag*(s[rt<<1|1].r-s[rt<<1|1].l+1));
        s[rt<<1].tag=(s[rt<<1].tag+s[rt].tag);
        s[rt<<1|1].tag=(s[rt<<1|1].tag+s[rt].tag);
        s[rt].tag=0;
    }
}
void build(long long rt,long long l,long long r)
{
    s[rt].l=l;
    s[rt].r=r;
    if(l==r)
    {   
        s[rt].sum=a[l];
        return;
    }
    long long mid=(l+r)>>1;
    build(rt<<1,l,mid);
    build(rt<<1|1,mid+1,r);
    up(rt);
}
void modify(long long rt,long long l,long long r,long long v)
{
    if(l<=s[rt].l&&r>=s[rt].r)
    {
        s[rt].sum+=(long long)v*(s[rt].r-s[rt].l+1);
        s[rt].tag+=v;
        return;
    }
    long long mid=(s[rt].l+s[rt].r)>>1;
    down(rt);
    if(l<=mid) modify(rt<<1,l,r,v);
    if(r>mid) modify(rt<<1|1,l,r,v);
    up(rt);
}
long long querry(long long rt,long long l,long long r)
{
    if(l<=s[rt].l&&r>=s[rt].r)
    {
        return s[rt].sum;
    }
    down(rt);
    long long ans=0;
    long long mid=(s[rt].r+s[rt].l)>>1;
    if(l<=mid) ans=(ans+querry(rt<<1,l,r));
    if(r>mid) ans=(ans+querry(rt<<1|1,l,r));
    return ans;
}


void dfs1(long long x,long long f,long long deep)
{
    fa[x]=f;
    dep[x]=deep;
    sz[x]=1;
    long long ms=-1;
    for(long long i=head[x];i;i=e[i].nex)
    {
        long long y=e[i].u;
        if(y==f) continue;
        dfs1(y,x,deep+1);
        sz[x]+=sz[y];
        if(ms<sz[y])
        {
            ms=sz[y];
            son[x]=y;
        }
    }
}
void dfs2(long long x,long long tt)
{
    id[x]=++num;
    a[num]=b[x];
    top[x]=tt;
    if(!son[x]) return;
    dfs2(son[x],tt);
    for(long long i=head[x];i;i=e[i].nex)
    {
        long long y=e[i].u;
        if(y==fa[x]||y==son[x]) continue;
        dfs2(y,y);
    }
}
long long q1(long long x,long long y)
{
   long long ans=0;
    while(top[x]!=top[y])
    {
        if(dep[top[x]]<dep[top[y]]) swap(x,y);
        ans+=querry(1,id[top[x]],id[x]);
        x=fa[top[x]];
    }
    if(dep[x]<dep[y]) swap(x,y);
    ans+=querry(1,id[y],id[x]);
    return ans;
}
void tree_modify(long long x,long long v)
{
    modify(1,id[x],id[x]+sz[x]-1,v);
}
int main()
{
    scanf("%lld%lld",&n,&m);
    for(long long i=1;i<=n;i++)
    scanf("%lld",&b[i]);
    for(long long i=1;i<=n-1;i++)
    {
        long long aa,bb;
        scanf("%lld%lld",&aa,&bb);
        add(aa,bb);
        add(bb,aa);
    }
        dfs1(1,0,1);
    dfs2(1,1);
    build(1,1,n);
    for(long long i=1;i<=m;i++)
    {
        scanf("%lld",&flag);
        if(flag==1)
            scanf("%lld%lld",&t,&res),modify(1,id[t],id[t],res);
        else if(flag==2)
            scanf("%lld%lld",&t,&res),tree_modify(t,res);
        else
            scanf("%lld",&t),printf("%lld\n",q1(1,t));
    }
    return 0;
}
P3178

 

 

洛谷P2486 染色(https://www.luogu.org/problem/P2486)

SDOI的一道题,线段树维护比较麻烦,需要维护区间左右端点的颜色以便合并时判重。

但更麻烦的是在合并链时链两端的判重。

啊这题真的好烦,但绝对是道好题QAQ ,由于有X,Y两个点往上走,所以要维护两条链的端点颜色,这样就需要再维护四个变量。

#include
#include
#include
#include
#include
using namespace std;
const int maxn=101000;
int b[maxn],id[maxn],top[maxn],dep[maxn],son[maxn],head[maxn],cul[maxn],sz[maxn],fa[maxn];
int n,m,cnt,num,p,q,aa,bb,cc,dd;
int link1,link2,lc,rc;
char o;
struct pp
{
    int l,r;
    int lc,rc;
    int tag,sum;
}s[maxn*4];
struct oo
{
    int u;
    int nex;
}e[maxn*2];


void add(int x,int y)
{
    e[++cnt].u=y;
    e[cnt].nex=head[x];
    head[x]=cnt;
}

void up(int rt)
{
    s[rt].lc=s[rt<<1].lc;
    s[rt].rc=s[rt<<1|1].rc;
    s[rt].sum=s[rt<<1].sum+s[rt<<1|1].sum;
    if(s[rt<<1].rc==s[rt<<1|1].lc)
    s[rt].sum--;
}
void down(int rt)
{
    if(s[rt].tag)
    {
        s[rt<<1].tag=s[rt<<1|1].tag=s[rt].tag;
        s[rt<<1].lc=s[rt<<1].rc=s[rt<<1|1].lc=s[rt<<1|1].rc=s[rt].lc;
        s[rt<<1].sum=s[rt<<1|1].sum=1;
        s[rt].tag=0;
    }
}
void build(int rt,int l,int r)
{
    s[rt].l=l;
    s[rt].r=r;
    if(l==r)
    {
        s[rt].sum=1;
        s[rt].lc=s[rt].rc=cul[l];
        return;
    }
    int mid=(s[rt].l+s[rt].r)>>1;
    build(rt<<1,l,mid);
    build(rt<<1|1,mid+1,r);
    up(rt);
}
void modify(int rt,int l,int r,int v)
{
    if(s[rt].l>=l&&s[rt].r<=r) 
    {
        s[rt].lc=s[rt].rc=v;
        s[rt].sum=s[rt].tag=1;
        return;
    }
    down(rt);
    int mid=(s[rt].l+s[rt].r)>>1;
    if(l<=mid) modify(rt<<1,l,r,v);
    if(r>mid) modify(rt<<1|1,l,r,v);
    up(rt);
}

void dfs1(int x,int f,int deep)
{
    fa[x]=f;
    dep[x]=deep;
    sz[x]=1;
    int ms=-1;
    for(int i=head[x];i;i=e[i].nex)
    {
        int y=e[i].u;
        if(y==f) continue;
        dfs1(y,x,deep+1);
        sz[x]+=sz[y];
        if(ms<sz[y]) 
        {
            son[x]=y;
            ms=sz[y];
        }
    }
}
int querry(int rt,int l,int r)
{
    if(l<=s[rt].l&&r>=s[rt].r)
    {
        if(l==s[rt].l ) lc=s[rt].lc;
        if(r==s[rt].r) rc=s[rt].rc;
        return s[rt].sum;
    }
        
    int ans=0;
    down(rt);
    int mid=(s[rt].l+s[rt].r)>>1;
    if(l<=mid) ans+=querry(rt<<1,l,r);
    if(r>mid) ans+=querry(rt<<1|1,l,r);
    if(l<=mid&&r>mid&&s[rt<<1].rc==s[rt<<1|1].lc)
    ans--;
    return ans ;
}
void dfs2(int x,int tt)
{
    id[x]=++num;
    cul[num]=b[x];
    top[x]=tt;
    if(!son[x]) return;
    dfs2(son[x],top[x]);
    for(int i=head[x];i;i=e[i].nex)
    {
        int y=e[i].u;
        if(y==fa[x]||y==son[x]) continue;
        dfs2(y,y);
    }
}

void treemodify(int x,int y,int v)
{
    while(top[x]!=top[y])
    {
        if(dep[top[x]]<dep[top[y]] ) swap(x,y);
        modify(1,id[top[x]],id[x],v);
        x=fa[top[x]];
    }
    if(dep[x]<dep[y]) swap(x,y);
    modify(1,id[y],id[x],v);
} 

int ask(int x,int y)
{
    int ans=0;
    link1=link2=-1;
    while(top[x]!=top[y])
    {
        if(dep[top[x]]<dep[top[y]]) swap(x,y),swap(link1,link2);
        ans+=querry(1,id[top[x]],id[x]);
        if(rc==link1) ans--;
        link1=lc;
        x=fa[top[x]];
    }
    if(dep[x]<dep[y]) swap(x,y),swap(link1,link2);
    ans+=querry(1,id[y],id[x]);
    if(rc==link1) ans--;
    if(lc==link2) ans--;
    return ans;
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
     scanf("%d",&b[i]);
    for(int i=1;i<=n-1;i++)
    {
        scanf("%d%d",&aa,&bb);
        add(aa,bb);
        add(bb,aa);
    }
    dfs1(1,0,1);
    dfs2(1,1);
    build(1,1,n);
    for(int i=1;i<=m;i++)
    {
        cin>>o;
        if(o=='C')
        {
            scanf("%d%d%d",&aa,&bb,&cc);
            treemodify(aa,bb,cc);
        }
        else 
        {
            scanf("%d%d",&aa,&bb);
            cout<<ask(aa,bb);
            printf("\n");
        }
    }
    return 0;
}
P2486

 

 

洛谷P2146 软件包管理器(https://www.luogu.org/problem/P2146)

啊挺模板的一道题,用到了区间覆盖的思想。

卸载后权值为0,安装了权值为1,每次询问求一下操作前后的权值差就OK了

#include
#include
#include
#include
#include
using namespace std;
const int MAXN=100010;
struct pp
{
    int l,r;
    int tag,sum;
}t[MAXN*4];
struct kk
{
    int u;
    int nex;
}e[MAXN*2];
int a[MAXN],b[MAXN],id[MAXN],sz[MAXN],son[MAXN],top[MAXN],fa[MAXN],dep[MAXN];
int head[MAXN];
int n,m,cnt,num,k,p,q,g,last;

void add(int x,int y)
{
    e[++cnt].u=y;
    e[cnt].nex=head[x];
    head[x]=cnt;
}

int ss(int rt)
{
    return (t[rt].r-t[rt].l+1);
}
void up(int rt)
{
    t[rt].sum=t[rt<<1].sum+t[rt<<1|1].sum;
}
void down(int rt)
{
    if(t[rt].tag!=-1)
    {
        t[rt<<1].sum=t[rt].tag*ss(rt<<1);
        t[rt<<1|1].sum=t[rt].tag*ss(rt<<1|1);
        t[rt<<1].tag=t[rt].tag;
        t[rt<<1|1].tag=t[rt].tag;
        t[rt].tag=-1;
    }
}
void build (int rt,int l,int r)
{
    t[rt].l=l;
    t[rt].r=r;
    t[rt].tag=-1;
    t[rt].sum=0;
    if(l==r) return;
    int mid=(l+r)>>1;
    build(rt<<1,l,mid);
    build(rt<<1|1,mid+1,r);
    up(rt);
}
 void modify(int rt,int l,int r,int v)
 {
     if(t[rt].l>=l&&t[rt].r<=r)
     {
         t[rt].sum=v*ss(rt);
         t[rt].tag=v;
         return;
     }
    down(rt);
    int mid=(t[rt].l+t[rt].r)>>1;
    if(l<=mid) modify(rt<<1,l,r,v);
    if(r>mid) modify(rt<<1|1,l,r,v);
    up(rt);
 }
 int quer(int rt,int l,int r)
 {
     if(t[rt].l>=l&&t[rt].r<=r)
     {
         return t[rt].sum;
     }
    down(rt);
    int ans=0;
    int mid=(t[rt].l+t[rt].r)>>1;
    if(l<=mid) ans+=quer(rt<<1,l,r);
    if(r>mid) ans+=quer(rt<<1|1,l,r);
    return ans;
 }
 
 
 
 
void dfs1(int x,int f,int deep)
{
    dep[x]=deep;
    fa[x]=f;
    sz[x]=1;
    int ms=-1;
    for(int i=head[x];i;i=e[i].nex)
    {
        int y=e[i].u;
        if(y==f) continue;
        dfs1(y,x,deep+1);
        sz[x]+=sz[y];
        if(sz[y]>ms)
        {
            ms=sz[y];
            son[x]=y;
        }
    }
}
void dfs2(int x,int tt)
{
    id[x]=++num;
    top[x]=tt;
    if(!son[x]) return;
    dfs2(son[x],tt);
    for(int i=head[x];i;i=e[i].nex)
    {
        int y=e[i].u;
        if(y==son[x]||y==fa[x]) continue;
        dfs2(y,y);
    }
}
int q1(int x,int y)
{
    int ans=0;
    while(top[x]!=top[y])
    {
        if(dep[top[x]]<dep[top[y]]) swap(x,y);
        ans+=quer(1,id[top[x]],id[x]);
        x=fa[top[x]];
    }
    if(dep[x]<dep[y]) swap(x,y);
    ans+=quer(1,id[y],id[x]);
    return ans;
}
void m1(int x,int y,int v)
{
    while(top[x]!=top[y])
    {
        if(dep[top[x]]<dep[top[y]]) swap(x,y);
        modify(1,id[top[x]],id[x],v);
        x=fa[top[x]];
    }
    if(dep[x]<dep[y]) swap(x,y);
    modify(1,id[y],id[x],v);
}
void tm(int x,int v)
{
    modify(1,id[x],id[x]+sz[x]-1,v);
}
int tq(int x)
{
    return quer(1,id[x],id[x]+sz[x]-1);
}

int main()
{
    string o;
    scanf("%d",&n);
    
    for(int i=1;i<=n-1;i++)
    {
        scanf("%d",&q);
        add(i+1,q+1);
        add(q+1,i+1);
    }
    dfs1(1,0,1);
    dfs2(1,1);
    build(1,1,n+1);
    scanf("%d",&m);
    for(int i=1;i<=m;i++)
    {
        cin>>o;
        scanf("%d",&k);
        k=k+1;
        if(o=="install")
        {
            last=q1(1,k);
            m1(1,k,1);
            g=q1(1,k);
            printf("%d\n",abs(g-last));
        
        }
        else
        {
            last=tq(k);
            tm(k,0);
            g=tq(k);
            printf("%d\n",abs(g-last));
        }
    }
    return 0;
}
P2146

 

你可能感兴趣的:(关于树剖板子的一些憨憨错误)