• 洛谷——P2781 传教


    P2781 传教

    题意很简单,就是要求你写一个数据结构,支持区间加法和区间查询

    显然,线段树模板嘛。。。

    不过$n<=10^9$,惊呆世人,啊哈,灵光一现,分块貌似可做,emmmm有感觉不行,$nlogn$?

    线段树空间是炸掉了,RE $50$分

    #include<bits/stdc++.h>
    
    #define  N 100000000
    using namespace std;
    
    struct node{
        int l,r,w,f;
    }tr[N];
    
    int n,m;
    
    void build(int k,int l,int r){
        tr[k].l=l,tr[k].r=r;
        if(l==r) return;
        int mid=(l+r)>>1;
        build(k<<1,l,mid);
        build(k<<1|1,mid+1,r);
    }
    
    void push(int k){
        if(tr[k].f){
            tr[k<<1].w+=(tr[k<<1].r-tr[k<<1].l+1)*tr[k].f;
            tr[k<<1].f+=tr[k].f;
            
            tr[k<<1|1].w+=(tr[k<<1|1].r-tr[k<<1|1].l+1)*tr[k].f;
            tr[k<<1|1].f+=tr[k].f;
            
            tr[k].f=0;
        }
    }
    void push_down(int k){
        tr[k].w=tr[k<<1].w+tr[k<<1|1].w;
    }
    void add(int k,int ql,int qr,int val){
        int l=tr[k].l,r=tr[k].r,mid=(l+r)>>1;
        if(l>=ql&&r<=qr) {tr[k].w+=(r-l+1)*val;tr[k].f+=val;return;}
        push(k);
        if(ql<=mid) add(k<<1,ql,qr,val);
        if(qr>mid) add(k<<1|1,ql,qr,val);
        push_down(k);
    }
    
    int ask(int k,int ql,int qr){
        int l=tr[k].l,r=tr[k].r,mid=(l+r)>>1;
        if(l>=ql&&r<=qr) return tr[k].w;
        push(k);
        int ans=0;
        if(ql<=mid) ans+=ask(k<<1,ql,qr);
        if(qr>mid) ans+=ask(k<<1|1,ql,qr);
        push_down(k);
        return ans;
    }
    
    int main()
    {
        scanf("%d%d",&n,&m);
        build(1,1,n);
        for(int opt,l,r,x,i=1;i<=m;i++){
            scanf("%d%d%d",&opt,&l,&r);
            if(opt==2) printf("%d
    ",ask(1,l,r));
            else scanf("%d",&x),add(1,l,r,x);
        }
        
        return 0;
    }

    转大佬博客

    动态开点线段树,指针写的,只好用指针,学习一下

    #include<bits/stdc++.h>
    
    #define  N 100000000
    #define LL long long
    using namespace std;
    
    struct node {
        LL w,f;
        node *lc,*rc;
        node() {
            w=f=0,lc=rc=NULL;
        }
        void push_up() {
            w=0;
            if(lc) w+=lc->w;
            if(rc) w+=rc->w;
        }
        void push_down(int l,int r){
            if(!lc) lc=new node();
            if(!rc) rc=new node();
            int mid=(l+r)>>1;
            lc->w+=(mid-l+1)*f,lc->f+=f;
            rc->w+=(r-mid)*f,rc->f+=f;
            f=0;
        }
    }*root=new node();
    
    int n,m,tot;
    
    void add(node *rt,int l,int r,int ql,int qr,LL val) {
        if(l>=ql&&r<=qr) {
            rt->w+=(r-l+1)*val;
            rt->f+=val;
            return;
        }
        rt->push_down(l,r);
        int mid=(l+r)>>1;
        if(ql<=mid) add(rt->lc,l,mid,ql,qr,val);
        if(qr>mid) add(rt->rc,mid+1,r,ql,qr,val);
        rt->push_up();
    }
    
    LL ask(node *rt,int l,int r,int ql,int qr) {
        if(l>=ql&&r<=qr) return rt->w;
        rt->push_down(l,r);
        LL ans=0;
        int mid=(l+r)>>1;
        if(ql<=mid) ans+=ask(rt->lc,l,mid,ql,qr);
        if(qr>mid) ans+=ask(rt->rc,mid+1,r,ql,qr);
        rt->push_up();
        return ans;
    }
    
    int main() {
        scanf("%d%d",&n,&m);
        for(int opt,l,r,x,i=1; i<=m; i++) {
            scanf("%d%d%d",&opt,&l,&r);
            if(opt==2) printf("%lld
    ",ask(root,1,n,l,r));
            else scanf("%d",&x),add(root,1,n,l,r,x);
        }
    
        return 0;
    }

    由于此题$m<=10^3$询问极少,可以暴力枚举前面的的区间

  • 相关阅读:
    Asp.net 连接池使用
    关于ASP.NET页面打印技术的总结
    Asp.net页面传值总结
    C#委托
    ASP.NET状态存储管理九大兵器
    JavaScript取ASP.NET中服务器端数据的方法
    DSOFramer.ocx 控件使用
    C#2.0 泛型学习(入门)
    黑马程序员——Java基础String与StringBuilder
    黑马程序员——Java基础语法关键字、常量、变量、运算符
  • 原文地址:https://www.cnblogs.com/song-/p/9792293.html
Copyright © 2020-2023  润新知