[树链剖分]

/*
HDU 3966
题意:
给n个结点,m条边,p次操作
I x y k
D x y k
x->y的路径上的节点都增加或减少k
Q x 查询x结点的权值

*/
#include <bits/stdc++.h>
using namespace std;
const int maxn = 50010;
int val[maxn],cnt,head[maxn],n;
int d[maxn],f[maxn],sz[maxn],son[maxn],top[maxn],id[maxn],tot,rk[maxn];
int t[maxn<<2],a[maxn],add[maxn<<2];

/*建图*/
struct node
{
    int to,next;
} e[maxn<<1];
void Init()
{
    memset(head,-1,sizeof(head));
    cnt=0;
    memset(son,-1,sizeof(son));
    tot=0;
}
void addEdge(int u,int v)
{
    e[cnt].to=v;
    e[cnt].next=head[u];
    head[u]=cnt++;
}

/*树链剖分*/
void dfs1(int u,int fa,int depth)
{
    f[u]=fa;
    d[u]=depth;
    sz[u]=1;
    for(int i=head[u]; ~i; i=e[i].next)
    {
        int v=e[i].to;
        if(v!=f[u])
        {
            dfs1(v,u,depth+1);
            sz[u]+=sz[v];
            if(son[u]==-1||sz[son[u]]<sz[v])
                son[u]=v;
        }
    }
}
void dfs2(int u,int tp)/*重新编号*/
{
    top[u]=tp;
    id[u]=++tot;
    rk[id[u]]=u;/*记录数组的第i个位置是编号为几的数*/
    if(son[u]==-1)
        return ;
    dfs2(son[u],tp);
    for(int i=head[u]; ~i; i=e[i].next)
    {
        int v=e[i].to;
        if(v!=f[u]&&v!=son[u])
            dfs2(v,v);
    }
}



/*线段树*/
void pushup(int cur)
{
    t[cur]=t[cur<<1]+t[cur<<1|1];
}
void pushdown(int cur,int l,int r)
{
    int mid=(l+r)>>1;
    if(add[cur])
    {
        add[cur<<1]+=add[cur];
        add[cur<<1|1]+=add[cur];
        t[cur<<1]+=add[cur]*(mid-l+1);
        t[cur<<1|1]+=add[cur]*(r-mid);
        add[cur]=0;
    }
}
void build(int cur,int l,int r)
{
    add[cur]=0;
    if(l==r)
    {
        t[cur]=val[rk[l]];
        return ;
    }
    int mid=(l+r)>>1;
    build(cur<<1,l,mid);
    build(cur<<1|1,mid+1,r);
}
void Update(int cur,int l,int r,int L,int R,int k)
{
    if(L<=l&&R>=r)
    {
        add[cur]+=k;
        t[cur]+=(r-l+1)*k;
        return ;
    }
    pushdown(cur,l,r);
    int mid=(l+r)>>1;
    if(L<=mid)
        Update(cur<<1,l,mid,L,R,k);
    if(R>mid)
        Update(cur<<1|1,mid+1,r,L,R,k);
    pushup(cur);
}
int Query(int cur,int l,int r,int index)
{
    int ans;
    if(l==r)
        return t[cur];
    pushdown(cur,l,r);
    int mid=(l+r)>>1;
    if(index<=mid)
        ans=Query(cur<<1,l,mid,index);
    else ans=Query(cur<<1|1,mid+1,r,index);
    // pushup(cur);
    return ans;
}
void Change(int x,int y,int val)
{
    while(top[x]!=top[y])
    {
        if(d[top[x]]<d[top[y]])
            swap(x,y);
        Update(1,1,n,id[top[x]],id[x],val);
        x=f[top[x]];
    }
    if(d[x]>d[y])
        swap(x,y);
    Update(1,1,n,id[x],id[y],val);
}
int main()
{
    int m,p,u,v,y,x,k;
    char s[110];
    while(~scanf("%d%d%d",&n,&m,&p))
    {
        Init();
        for(int i=1; i<=n; i++)
            scanf("%d",&val[i]);
        for(int i=1; i<n; i++)
        {
            scanf("%d%d",&u,&v);
            addEdge(u,v);
            addEdge(v,u);
        }

        dfs1(1,0,1);
        dfs2(1,1);
        build(1,1,n);

        while(p--)
        {
            scanf("%s",s);
            if(s[0]=='Q')
            {
                scanf("%d",&x);
                printf("%d\n",Query(1,1,n,id[x]));
            }
            else
            {
                scanf("%d%d%d",&x,&y,&k);
                if(s[0]=='D')
                    k=-k;
                Change(x,y,k);
            }
        }
    }
    return 0;
}
/*
10 9 5
1 2 3 4 5 6 7 8 9 10
1 2
1 3
2 8
3 5
3 4
5 7
5 6
4 9
9 10
*/












/*FZU 2082 更新边权*/
#include <cstdio>
#include <cstring>
#include <algorithm>
typedef long long LL;
using namespace std;
const int maxn=50010;
struct node
{
    int to,next,w,id;
} e[maxn<<1];
int n,head[maxn],cnt,f[maxn],d[maxn],son[maxn],sz[maxn],val[maxn],ee[maxn],tot,top[maxn],id[maxn],rk[maxn];
void Init()
{
    memset(head,-1,sizeof(head));
    cnt=0;
    memset(son,-1,sizeof(son));
    tot=0;
}
void add(int u,int v,int w,int id)
{
    e[cnt].to=v;
    e[cnt].w=w;
    e[cnt].id=id;
    e[cnt].next=head[u];
    head[u]=cnt++;
}
void dfs1(int u,int fa,int depth,int w,int pos)
{
    f[u]=fa;/*记录父亲*/
    d[u]=depth;/*记录深度*/
    sz[u]=1;/*记录孩子个数,选择重边*/
    val[u]=w;/*以u为终点的边的权值为w*/
    ee[pos]=u;/*第pos条边的终点为u*/
    for(int i=head[u]; ~i; i=e[i].next)
    {
        int v=e[i].to;
        if(v!=fa)
        {
            dfs1(v,u,depth+1,e[i].w,e[i].id);
            sz[u]+=sz[v];
            if(son[u]==-1||sz[son[u]]<sz[v])
                son[u]=v;
        }
    }
}
void dfs2(int u,int tp)/*将同一条链的结点映射到连续的一段区间[]*/
{
    top[u]=tp;
    id[u]=++tot;
    rk[id[u]]=u;
    if(son[u]==-1)
        return ;
    dfs2(son[u],tp);
    for(int i=head[u]; ~i; i=e[i].next)
    {
        int v=e[i].to;
        if(v!=f[u]&&v!=son[u])
            dfs2(v,v);
    }
}
/*线段树 单点更新 区间查询*/
LL t[maxn<<2];
void pushup(int cur)
{
    t[cur]=t[cur<<1]+t[cur<<1|1];
}
void build(int cur,int l,int r)
{
    if(l==r)
    {
        t[cur]=val[rk[l]];
        return ;
    }
    int mid=(l+r)>>1;
    build(cur<<1,l,mid);
    build(cur<<1|1,mid+1,r);
    pushup(cur);
}
void Update(int cur,int l,int r,int index,int k)
{
    if(l==r)
    {
        t[cur]=k;
        return ;
    }
    int mid=(l+r)>>1;
    if(index<=mid)
        Update(cur<<1,l,mid,index,k);
    else Update(cur<<1|1,mid+1,r,index,k);
    pushup(cur);
}
LL Query(int cur,int l,int r,int L,int R)
{
    LL ans=0;
    if(L<=l&&R>=r)
    {
        return t[cur];
    }
    int mid=(l+r)>>1;
    if(L<=mid)
        ans+=Query(cur<<1,l,mid,L,R);
    if(R>mid)
        ans+=Query(cur<<1|1,mid+1,r,L,R);
    return ans;
}
void Change(int u,int v)
{
    LL ans=0;
    while(top[u]!=top[v])
    {
        if(d[top[u]]<d[top[v]])
            swap(u,v);
        ans+=Query(1,1,n,id[top[u]],id[u]);
        u=f[top[u]];
    }
    if(d[u]>d[v])
        swap(u,v);
    ans+=Query(1,1,n,id[u]+1,id[v]);
    printf("%lld\n",ans);
}
int main()
{
    int m,u,v,w,op,x,y;
    while(~scanf("%d%d",&n,&m))
    {
        Init();
        for(int i=1; i<n; i++)
        {
            scanf("%d%d%d",&u,&v,&w);
            add(u,v,w,i);
            add(v,u,w,i);
        }
        dfs1(1,0,0,0,0);
        dfs2(1,1);
        build(1,1,n);
        while(m--)
        {
            scanf("%d%d%d",&op,&x,&y);
            if(op==0)
            {
                Update(1,1,n,id[ee[x]],y);
            }
            else
            {
                Change(x,y);
            }
        }
    }
    return 0;
}

//BZOJ 1036 更新点权
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
const int maxn=30010;
int val[maxn],n;
int head[maxn],cnt,d[maxn],f[maxn],sz[maxn],son[maxn],id[maxn],tot,rk[maxn],top[maxn];
struct node
{
    int to,next;
} e[maxn<<1];
struct pp
{
    int sum,Max;
} t[maxn<<2];
void Init()
{
    memset(head,-1,sizeof(head));
    cnt=0;
    memset(son,-1,sizeof(son));
    tot=0;
}
void addEdge(int u,int v)
{
    e[cnt].to=v;
    e[cnt].next=head[u];
    head[u]=cnt++;
}
void dfs1(int u,int fa,int depth)
{
    d[u]=depth;
    f[u]=fa;
    sz[u]=1;
    for(int i=head[u]; ~i; i=e[i].next)
    {
        int v=e[i].to;
        if(v!=fa)
        {
            dfs1(v,u,depth+1);
            sz[u]+=sz[v];
            if(son[u]==-1||sz[son[u]]<sz[v])
                son[u]=v;
        }
    }
}
void dfs2(int u,int tp)
{
    top[u]=tp;
    id[u]=++tot;
    rk[id[u]]=u;
    if(son[u]==-1)
        return ;
    dfs2(son[u],tp);
    for(int i=head[u]; ~i; i=e[i].next)
    {
        int v=e[i].to;
        if(v!=f[u]&&son[u]!=v)
            dfs2(v,v);
    }
}
void pushup(int cur)
{
    t[cur].sum=t[cur<<1].sum+t[cur<<1|1].sum;
    t[cur].Max=max(t[cur<<1].Max,t[cur<<1|1].Max);
}
void build(int cur,int l,int r)
{
    if(l==r)
    {
        t[cur].Max=t[cur].sum=val[rk[l]];
        return ;
    }
    int mid=(l+r)>>1;
    build(cur<<1,l,mid);
    build(cur<<1|1,mid+1,r);
    pushup(cur);
}
void Update(int cur,int l,int r,int index,int k)
{
    if(l==r)
    {
        t[cur].Max=t[cur].sum=k;
        return ;
    }
    int mid=(l+r)>>1;
    if(index<=mid)
        Update(cur<<1,l,mid,index,k);
    else
        Update(cur<<1|1,mid+1,r,index,k);
    pushup(cur);
}
int Query(int cur,int l,int r,int L,int R,int flag)
{
    // printf("l = %d r = %d\n",l,r);

    int ans;
    if(flag)
        ans=-INF;/*数据权值有负数 之前设ans=0 WA*/
    else ans=0;
    if(L<=l&&R>=r)
    {
        if(flag)
            return t[cur].Max;
        else return t[cur].sum;
    }
    int mid=(l+r)>>1;
    if(L<=mid)
    {
        if(flag)
            ans=max(ans,Query(cur<<1,l,mid,L,R,flag));
        else ans+=Query(cur<<1,l,mid,L,R,flag);
    }
    if(R>mid)
    {
        if(flag)
            ans=max(ans,Query(cur<<1|1,mid+1,r,L,R,flag));
        else ans+=Query(cur<<1|1,mid+1,r,L,R,flag);
    }
    return ans;//没返回值 debug了好久。。
}
void Change(int u,int v,int flag)
{
    int ans;
    if(flag)
        ans=-INF;
    else ans=0;
    while(top[u]!=top[v])
    {
        if(d[top[u]]<d[top[v]])
            swap(u,v);
        if(flag)ans=max(ans,Query(1,1,n,id[top[u]],id[u],flag));
        else ans+=Query(1,1,n,id[top[u]],id[u],flag);
        u=f[top[u]];
    }
    if(d[u]>d[v])
        swap(u,v);
    if(flag)
        ans=max(ans,Query(1,1,n,id[u],id[v],flag));
    else ans+=Query(1,1,n,id[u],id[v],flag);
    printf("%d\n",ans);
}
int main()
{
    int u,v,x,y,q;
    char s[110];
    scanf("%d",&n);
    Init();
    for(int i=1; i<n; i++)
    {
        scanf("%d%d",&u,&v);
        addEdge(u,v);
        addEdge(v,u);
    }
    for(int i=1; i<=n; i++)
        scanf("%d",&val[i]);

    dfs1(1,0,0);
    dfs2(1,1); //
    build(1,1,n);
    scanf("%d",&q);
    while(q--)
    {
        scanf("%s",s);
        if(s[0]=='C')
        {
            scanf("%d%d",&x,&y);
            Update(1,1,n,id[x],y);
        }
        else
        {
            scanf("%d%d",&x,&y);
            if(s[1]=='M')
                Change(x,y,1);
            else
                Change(x,y,0);
        }
    }
    return 0;
}

【使用教程】 一、环境配置 1、建议下载anaconda和pycharm 在anaconda中配置好环境,然后直接导入到pycharm中,在pycharm中运行项目 anaconda和pycharm安装及环境配置参考网上博客,有很多博主介绍 2、在anacodna中安装requirements.txt中的软件包 命令为:pip install -r requirements.txt 或者改成清华源后再执行以上命令,这样安装要快一些 软件包都安装成功后才算成功 3、安装好软件包后,把anaconda中对应的python导入到pycharm中即可(不难,参考网上博客) 二、环境配置好后,开始训练(也可以训练自己数据集) 1、数据集准备 需要准备yolo格式的目标检测数据集,如果不清楚yolo数据集格式,或者有其他数据训练需求,请看博主yolo格式各种数据集集合链接:https://blog.csdn.net/DeepLearning_/article/details/127276492 里面涵盖了上百种yolo数据集,且在不断更新,基本都是实际项目使用。来自于网上收集、实际场景采集制作等,自己使用labelimg标注工具标注的。数据集质量绝对有保证! 本项目所使用的数据集,见csdn该资源下载页面中的介绍栏,里面有对应的下载链接,下载后可直接使用。 2、数据准备好,开始修改配置文件 参考代码中data文件夹下的banana_ripe.yaml,可以自己新建一个不同名称的yaml文件 train:训练集的图片路径 val:验证集的图片路径 names: 0: very-ripe 类别1 1: immature 类别2 2: mid-ripe 类别3 格式按照banana_ripe.yaml照葫芦画瓢就行,不需要过多参考网上的 3、修改train_dual.py中的配置参数,开始训练模型 方式一: 修改点: a.--weights参数,填入'yolov9-s.pt',博主训练的是yolov9-s,根据自己需求可自定义 b.--cfg参数,填入 models/detect/yolov9-c.yaml c.--data参数,填入data/banana_ripe.yaml,可自定义自己的yaml路径 d.--hyp参数,填入hyp.scratch-high.yaml e.--epochs参数,填入100或者200都行,根据自己的数据集可改 f.--batch-size参数,根据自己的电脑性能(显存大小)自定义修改 g.--device参数,一张显卡的话,就填0。没显卡,使用cpu训练,就填cpu h.--close-mosaic参数,填入15 以上修改好,直接pycharm中运行train_dual.py开始训练 方式二: 命令行方式,在pycharm中的终端窗口输入如下命令,可根据自己情况修改参数 官方示例:python train_dual.py --workers 8 --device 0 --batch 16 --data data/coco.yaml --img 640 --cfg models/detect/yolov9-c.yaml --weights '' --name yolov9-c --hyp hyp.scratch-high.yaml --min-items 0 --epochs 500 --close-mosaic 15 训练完会在runs/train文件下生成对应的训练文件及模型,后续测试可以拿来用。 三、测试 1、训练完,测试 修改detect_dual.py中的参数 --weights,改成上面训练得到的best.pt对应的路径 --source,需要测试的数据图片存放的位置,代码中的test_imgs --conf-thres,置信度阈值,自定义修改 --iou-thres,iou阈值,自定义修改 其他默认即可 pycharm中运行detect_dual.py 在runs/detect文件夹下存放检测结果图片或者视频 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用!有问题请及时沟通交流。 2、适用人群:计算机相关专业(如计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网、自动化、电子信息等)在校学生、专业老师或者企业员工下载使用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值