zoukankan      html  css  js  c++  java
  • codevs 线段树练习ⅠⅡⅢ

    1080 线段树练习

     

     时间限制: 1 s
     空间限制: 128000 KB
     题目等级 : 钻石 Diamond
     
     
     
    题目描述 Description

    一行N个方格,开始每个格子里都有一个整数。现在动态地提出一些问题和修改:提问的形式是求某一个特定的子区间[a,b]中所有元素的和;修改的规则是指定某一个格子x,加上或者减去一个特定的值A。现在要求你能对每个提问作出正确的回答。1≤N<100000,,提问和修改的总数m<10000条。

    输入描述 Input Description

    输入文件第一行为一个整数N,接下来是n行n个整数,表示格子中原来的整数。接下一个正整数m,再接下来有m行,表示m个询问,第一个整数表示询问代号,询问代号1表示增加,后面的两个数x和A表示给位置X上的数值增加A,询问代号2表示区间求和,后面两个整数表示a和b,表示要求[a,b]之间的区间和。

    输出描述 Output Description

    共m行,每个整数

    样例输入 Sample Input

    6

    3

    4

    1 3 5

    2 1 4

    1 1 9

    2 2 6

    样例输出 Sample Output

    22

    22

    数据范围及提示 Data Size & Hint

    1≤N≤100000, m≤10000 。

    #include <cstdio>
    #include <iostream>
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    const int maxn=1000005;
    using namespace std;
    int sum[maxn<<2];
    
    void PushUP(int rt) 
    {
        sum[rt]=sum[rt<<1]+sum[rt<<1|1];//将两条小区间合并成一个大区间 
    }
    
    void build(int l,int r,int rt) 
    {
        if (l==r)//最底层的节点 
        {
            scanf("%d",&sum[rt]);//读入节点的值 
            return;
        }
        int m=(l+r)>>1;//分成两个区间 
        build(lson);//分别搞搞左右两个区间 
        build(rson);
        PushUP(rt);//将最底层的节点的值传入上层节点 
    }
    
    void update(int p,int add,int l,int r,int rt) 
    {
        if (l==r)//往最底层节点加上add 
        {
            sum[rt]+=add;
            return;
        }
        int m=(l+r)>>1;//取中间节点 
        if (p<=m)update(p,add,lson);//找到节点的儿子并且是p的祖先的节点,递归到p 
        else update(p,add,rson);
        PushUP(rt);//更新p祖先节点的值 
    }
    
    int query(int L,int R,int l,int r,int rt)//区间查询 
    {//L,R是要查询的区间和,l、r是目前的区间,rt是目前的节点 
        if (L<=l&&r<=R) 
        {
            return sum[rt];//如果当前区间是所求区间的一部分,就加上这段区间 
        }
        int m=(l+r)>>1;//二分当前区间 
        int ret=0;//为所求区间的数值和 
        if (L<=m)ret+=query(L,R,lson);//加上所需区间 
        if (R>m)ret+=query(L,R,rson);
        return ret;
    }
    
    int main() 
    {
        int n,m;
        scanf("%d",&n);//区间为1-n 
        build(1,n,1);//建树 
        int cz;
        cin>>m; 
        while(m--) 
        {
            scanf("%d",&cz); 
            int a,b;
            scanf("%d%d",&a,&b);
            if (cz==2)printf("%d
    ",query(a,b,1,n,1));//query 询问区间的总值 
            //else if (cz==3)update(a,-b,1,n,1);//sub 往第a个数里减b 
            else update(a,b,1,n,1);//往第a个数中加b 
        }
        return 0;
    }

    给你N个数,有两种操作


    1:给区间[a,b]的所有数都增加X


    2:询问第i个数是什么?

    输入描述 Input Description

    第一行一个正整数n,接下来n行n个整数,再接下来一个正整数Q,表示操作的个数. 接下来Q行每行若干个整数。如果第一个数是1,后接3个正整数a,b,X,表示在区间[a,b]内每个数增加X,如果是2,后面跟1个整数i, 表示询问第i个位置的数是多少。

    输出描述 Output Description

    对于每个询问输出一行一个答案

    样例输入 Sample Input

    3

    1

    2

    3

    2

    1 2 3 2

    2 3

    样例输出 Sample Output

    5

    数据范围及提示 Data Size & Hint

    数据范围

    1<=n<=100000

    1<=q<=100000

    #include <cstdio>
    #include <iostream>
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    const int maxn=1000005;
    using namespace std;
    int sum[maxn<<2];
    
    void PushUP(int rt) 
    {
        sum[rt]=sum[rt<<1]+sum[rt<<1|1];//将两条小区间合并成一个大区间 
    }
    
    void build(int l,int r,int rt) 
    {
        if (l==r)//最底层的节点 
        {
            scanf("%d",&sum[rt]);//读入节点的值 
            return;
        }
        int m=(l+r)>>1;//分成两个区间 
        build(lson);//分别搞搞左右两个区间 
        build(rson);
        PushUP(rt);//将最底层的节点的值传入上层节点 
    }
    
    void update(int p,int add,int l,int r,int rt) 
    {
        if (l==r)//往最底层节点加上add 
        {
            sum[rt]+=add;
            return;
        }
        int m=(l+r)>>1;//取中间节点 
        if (p<=m)update(p,add,lson);//找到节点的儿子并且是p的祖先的节点,递归到p 
        else update(p,add,rson);
        PushUP(rt);//更新p祖先节点的值 
    }
    
    int query(int L,int R,int l,int r,int rt)//区间查询 
    {//L,R是要查询的区间和,l、r是目前的区间,rt是目前的节点 
        if (L<=l&&r<=R) 
        {
            return sum[rt];//如果当前区间是所求区间的一部分,就加上这段区间 
        }
        int m=(l+r)>>1;//二分当前区间 
        int ret=0;//为所求区间的数值和 
        if (L<=m)ret+=query(L,R,lson);//加上所需区间 
        if (R>m)ret+=query(L,R,rson);
        return ret;
    }
    
    int main() 
    {
        int n,m;
        scanf("%d",&n);//区间为1-n 
        build(1,n,1);//建树 
        int cz;
        cin>>m; 
        while(m--) 
        {
            scanf("%d",&cz); 
            int a,b,c;
            if (cz==1)
            {
                cin>>a>>b>>c;
                for(int i=a;i<=b;++i)
                    update(i,c,1,n,1);
            }
            else 
            {
                cin>>a;
                cout<<query(a,a,1,n,1)<<endl;
            }
        }
        return 0;
    }
    题目描述 Description

    给你N个数,有两种操作:


    1:给区间[a,b]的所有数增加X


    2:询问区间[a,b]的数的和。

    输入描述 Input Description

    第一行一个正整数n,接下来n行n个整数,

    再接下来一个正整数Q,每行表示操作的个数,

    如果第一个数是1,后接3个正整数,

    表示在区间[a,b]内每个数增加X,如果是2,

    表示操作2询问区间[a,b]的和是多少。

    pascal选手请不要使用readln读入

    输出描述 Output Description

    对于每个询问输出一行一个答案

    样例输入 Sample Input

    3

    1

    2

    3

    2

    1 2 3 2

    2 2 3

    样例输出 Sample Output

    9

    数据范围及提示 Data Size & Hint

    数据范围

    1<=n<=200000

    1<=q<=200000

     
    #include<cstdio>  
    #include<cstring>
    #include<iostream>  
    #include<algorithm>  
    using namespace std;  
    #define N 500005  
    #define lson l,m,rt<<1  
    #define rson m+1,r,rt<<1|1  
    #define ll long long  
    ll sum[N*4];  
    int visit[N*4];  
    void pushUp(int rt)  
    {  
        sum[rt]=sum[rt<<1]+sum[rt<<1|1];  
    }  
    
    void build(int l,int r,int rt)  
    {  
        visit[rt]=0;  
        if(l==r)  
        {  
            scanf("%lld",&sum[rt]);  
            return ;  
        }  
        int m=(l+r)>>1;  
        build(lson);  
        build(rson);  
        pushUp(rt);  
    }  
    
    void pushDown(int rt,int d)  
    {  
        if(visit[rt]!=0)  
        {  
        
           visit[rt<<1]+=visit[rt];  
           visit[rt<<1|1]+=visit[rt];  
            sum[rt<<1|1]+=(ll)(d>>1)*visit[rt];
            sum[rt<<1]+=(ll)(d-(d>>1))*visit[rt];  
            visit[rt]=0;  
        }  
    }  
    
    void update(int L,int R,int c,int l,int r,int rt)  
    {  
        if(L<=l && R>=r)  
        {  
            visit[rt]+=c;  
            sum[rt]+=(r-l+1)*c;  
            return ;  
        }  
        pushDown(rt,r-l+1);  
        int m=(l+r)>>1;  
        if(L<=m)  
            update(L,R,c,lson);  
        if(R>m)  
            update(L,R,c,rson);  
        pushUp(rt);  
    }
      
    ll query(int L,int R,int l,int r,int rt)  
    {  
        if(L<=l&&R>=r)  
        {  
            return sum[rt];  
        }   
        pushDown(rt,r-l+1);  
        int m=(l+r)>>1;  
        ll ret=0;  
        if(L<=m)  
            ret+=query(L,R,lson);  
        if(R>m)  
            ret+=query(L,R,rson);  
        return ret;  
    }  
    
    int main()  
    {  
        int n,q,a,b,c;  
        int s;  
        scanf("%d",&n);  
        build(1,n,1);
        cin>>q;  
        while(q--)  
        {  
            scanf("%d",&s);  
            if(s==1)  
            {  
                scanf("%d%d%d",&a,&b,&c);  
                update(a,b,c,1,n,1);  
            }  
            else if(s==2)  
            {  
                scanf("%d%d",&a,&b);  
                printf("%lld
    ",query(a,b,1,n,1));  
            }  
        }  
        return 0;  
    }
  • 相关阅读:
    c语言结构体数组引用
    c语言结构体数组定义的三种方式
    如何为SAP WebIDE开发扩展(Extension),并部署到SAP云平台上
    SAP SRM ABAP Webdynpro和CFCA usb key集成的一个原型开发
    使用SAP API portal进行SAP SuccessFactors的API测试
    SAP UI5应用里的页面路由处理
    在SAP WebIDE Database Explorer里操作hdi实例
    如何使用SAP事务码SAT进行UI应用的性能分析
    使用SAP WebIDE进行SAP Cloud Platform Business Application开发
    SAP CRM WebClient UI ON_NEW_FOCUS的用途
  • 原文地址:https://www.cnblogs.com/qdscwyy/p/6904506.html
Copyright © 2011-2022 走看看