9.26NOIP模拟 树链剖分

本文介绍了一种使用树状结构进行区间修改和查询的方法,并通过一个具体的例子详细展示了如何构建和操作这种数据结构。文章包括了核心算法的实现细节,如节点的下传、区间加法和赋值等操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这道题调了那么久居然是最后的judge错了……
没有考虑m=0和m=1的情况

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=100000+5;
int n,m;
int a[N];
int to[2*N],nxt[2*N],head[N],etot;
int dep[N],fat[N],son[N],size[N];
int top[N],in[N],seq[N],idc;
int prime[N],siz;bool isprime[N];
struct node{
    node *ls,*rs;
    int vsum,del,chg;
    void pushdown(int lf,int rg){
        int mid=(lf+rg)>>1;
        if(chg!=-1){
            ls->chg=chg;
            rs->chg=chg;
            ls->del=0;
            rs->del=0;
            ls->vsum=(mid-lf+1)*chg;
            rs->vsum=(rg-mid)*chg;
            chg=-1;
        }
        if(del!=0){
            ls->del+=del;
            rs->del+=del;
            ls->vsum+=(mid-lf+1)*del;//(ls->del);
            rs->vsum+=(rg-mid)*del;//(rs->del);
            //若子节点之前也有del说明之前也更新到过它,那del已经加给它过了
            //这次只用加这次的del即可 
            del=0;
        }
    }
}pool[2*N+5],*tail=pool,*rt;
void adde(int u,int v)
{
    to[++etot]=v;
    nxt[etot]=head[u];
    head[u]=etot;
}
void dfs1(int u,int fa)
{
    dep[u]=dep[fa]+1;
    fat[u]=fa;
    size[u]=1;
    for(int i=head[u];i;i=nxt[i]){
        int v=to[i];
        if(v==fa) continue;
        dfs1(v,u);
        if(son[u]==-1||size[v]>size[son[u]]) son[u]=v;
        size[u]+=size[v];
    }
}
void dfs2(int u,int tp)
{
    top[u]=tp;
    in[u]=++idc;
    seq[idc]=u;
    if(son[u]!=-1) dfs2(son[u],tp);
    for(int i=head[u];i;i=nxt[i]){
        int v=to[i];
        if(v==fat[u]||v==son[u]) continue;
        dfs2(v,v);
    }
}
node *build(int lf,int rg)
{
    node *nd=++tail;
    if(lf==rg){
        nd->vsum=a[seq[lf]];
        nd->del=0;
        nd->chg=-1;
        return nd;
    }
    int mid=(lf+rg)>>1;
    nd->ls=build(lf,mid);
    nd->rs=build(mid+1,rg);
    nd->del=0;
    nd->chg=-1;
    nd->vsum=nd->ls->vsum+nd->rs->vsum;
//  nd->update();
    return nd;
}
void modify_del(node *nd,int L,int R,int lf,int rg,int del)
{
    if(L<=lf&&rg<=R){
        //这个点已经没有原来的chg del的干扰了 
        nd->vsum+=del*(rg-lf+1);
        nd->del+=del;
        return;
        //有标记的意义在于表示它的标记还没有向下传递,但是它已经被标记更新了 
    }
    nd->pushdown(lf,rg);
    int mid=(lf+rg)>>1;
    if(L<=mid)  modify_del(nd->ls,L,R,lf,mid,del);
    if(R>mid) modify_del(nd->rs,L,R,mid+1,rg,del);
    nd->vsum=nd->ls->vsum+nd->rs->vsum;
}
void modify_del(int u,int v,int del)
{
    while(top[u]!=top[v]){
        if(dep[top[u]]<dep[top[v]]) swap(u,v);
        modify_del(rt,in[top[u]],in[u],1,n,del);
        u=fat[top[u]];
    }
    if(dep[u]<dep[v]) swap(u,v);
    modify_del(rt,in[v],in[u],1,n,del);
}
void modify_chg(node *nd,int L,int R,int lf,int rg,int val)
{
    if(L<=lf&&rg<=R){
        nd->del=0;
        nd->chg=val;
        nd->vsum=val*(rg-lf+1);
        return;
    }
    nd->pushdown(lf,rg);
    int mid=(lf+rg)>>1;
    if(L<=mid) modify_chg(nd->ls,L,R,lf,mid,val);
    if(R>mid) modify_chg(nd->rs,L,R,mid+1,rg,val);
    nd->vsum=nd->ls->vsum+nd->rs->vsum;
}
void modify_chg(int u,int v,int val)
{
    while(top[u]!=top[v]){
        if(dep[top[u]]<dep[top[v]]) swap(u,v);
        modify_chg(rt,in[top[u]],in[u],1,n,val);
        u=fat[top[u]];
    }
    if(dep[u]<dep[v]) swap(u,v);
    modify_chg(rt,in[v],in[u],1,n,val);
}
int query(node *nd,int L,int R,int lf,int rg)
{
    if(L<=lf&&rg<=R)
        return nd->vsum;
    nd->pushdown(lf,rg);
    int mid=(lf+rg)>>1;
    int ans=0;
    if(L<=mid) ans+=query(nd->ls,L,R,lf,mid);
    if(R>mid) ans+=query(nd->rs,L,R,mid+1,rg);
    nd->vsum=nd->ls->vsum+nd->rs->vsum;
    return ans;
}
int query(int u,int v)
{
    int ans=0;
    while(top[u]!=top[v]){
        if(dep[top[u]]<dep[top[v]]) swap(u,v);
        ans+=query(rt,in[top[u]],in[u],1,n);
        u=fat[top[u]];
    }
    if(dep[u]<dep[v]) swap(u,v);
    ans+=query(rt,in[v],in[u],1,n);
    return ans;
}
bool judge(int x)
{
    if(x==2) return 0;
    if(!(x%2)) return 1;
    if(x-2<=100000){
        if(isprime[x-2]) return 1;
        else return 0;
    }
    else {
        for(int i=2;i*i<=x-2;i++)
        if((x-2)%i==0) return 0;
        return 1;   
    }
}
void euler(int primesize)
{
    isprime[1]=0;
    memset(isprime,1,sizeof(isprime));
    for(int i=2;i<=primesize;i++){
        if(isprime[i]) prime[++siz]=i;
        for(int j=1;prime[j]*i<=primesize&&j<=siz;j++){
            isprime[i*prime[j]]=0;
            if(!(i%prime[j])) break;
        }
    }
}
int main()
{
    freopen("japari.in","r",stdin);
    freopen("japari.out","w",stdout);
    euler(100000);
    memset(son,-1,sizeof(son));
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    for(int i=1;i<n;i++){
        int u,v;
        scanf("%d%d",&u,&v);
        adde(u,v),adde(v,u);
    }
    dfs1(1,1);
    dfs2(1,1);
    rt=build(1,n);
    while(m--){
        int opt,x,y,v;
        scanf("%d",&opt);
        if(opt==1){
            scanf("%d%d%d",&x,&y,&v);
            modify_del(x,y,v);
        }
        if(opt==2){
            scanf("%d%d%d",&x,&y,&v);
            modify_chg(x,y,v);
        }
        if(opt==3){
            scanf("%d%d",&x,&y);
            int m=query(x,y);
            if(judge(m)) printf("SUGOI\n");
            else printf("TANOSHI\n");
        }
    }
    return 0;
}
基于Spring Boot搭建的一个多功能在线学习系统的实现细节。系统分为管理员和用户两个主要模块。管理员负责视频、文件和文章资料的管理以及系统运营维护;用户则可以进行视频播放、资料下载、参与学习论坛并享受个性化学习服务。文中重点探讨了文件下载的安全性和性能优化(如使用Resource对象避免内存溢出),积分排行榜的高效实现(采用Redis Sorted Set结构),敏感词过滤机制(利用DFA算法构建内存过滤)以及视频播放的浏览器兼容性解决方案(通过FFmpeg调整MOOV原子位置)。此外,还提到了权限管理方面自定义动态加载器的应用,提高了系统的灵活性和易用性。 适合人群:对Spring Boot有一定了解,希望深入理解其实际应用的技术人员,尤其是从事在线教育平台开发的相关从业者。 使用场景及目标:适用于需要快速搭建稳定高效的在线学习平台的企业或团队。目标在于提供一套完整的解决方案,涵盖从资源管理到用户体验优化等多个方面,帮助开发者更好地理解和掌握Spring Boot框架的实际运用技巧。 其他说明:文中不仅提供了具体的代码示例和技术思路,还分享了许多实践经验教训,对于提高项目质量有着重要的指导意义。同时强调了安全性、性能优化等方面的重要性,确保系统能够应对大规模用户的并发访问需求。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值