• 士兵杀敌(四)


    题目

    解决方案一:线段树   1916ms   47100B   C/C++

    可以看到用线段树解决非常的浪费空间

    #include <iostream>
    #include <cstdio>
    using namespace std;
    #define L(x) (x<<1)
    #define R(x) ((x<<1)+1)
    #define M(x,y) ((x+y)>>1)
    const int N=1000005;
    struct node
    {
        int l,r,score;
    };
    node tree[4*N];
    /*
    此处建立的线段树为[a,b][b+1,c]类型,由于询问的是点的大小 
    */
    void build(int t,int l,int r)
    {
        tree[t].l=l;
        tree[t].r=r;
        tree[t].score=0;
        if(l==r)return;
        int mid=M(l,r);
        build(L(t),l,mid);
        build(R(t),mid+1,r);
    }
    void updata(int t,int l,int r,int inc)
    {
        if(tree[t].l>=l && tree[t].r<=r)
        {
            tree[t].score+=inc;
            return;
        }
        int mid=M(tree[t].l,tree[t].r);
        if(r<=mid)updata(L(t),l,r,inc);
        else if(l>mid)updata(R(t),l,r,inc);
        else 
        {
            updata(L(t),l,mid,inc);
            updata(R(t),mid+1,r,inc);
        }
    }
    void query(int t,int n)
    {
        if(tree[t].l==tree[t].r )
        {
            printf("%d\n",tree[t].score);
            return ;
        }
        if(tree[t].score) 
        {
            /*
            这个地方由于写成了tree[L(t)].score=tree[R(t)].score=tree[t].score;而导致错误
            因为当儿子节点修改时,也可能本身就存在着值,所以应该在原有的基础上加上当前的
            score而不是简单复制过去 
            */ 
            tree[L(t)].score+=tree[t].score;
            tree[R(t)].score+=tree[t].score;
            tree[t].score=0;        
        }
        //此处本来不应该有问题,但是由于求mid时少写了M(tree[t].l,tree[t].r) 中的M函数名,让我找bug找了
        //半个小时 
        int mid=M(tree[t].l,tree[t].r);
        if(n<=mid)query(L(t),n);
        else query(R(t),n);
    }
    
    int main()
    {
        int t,m;
        scanf("%d%d",&t,&m);
        build(1,1,m);
        char cmd[10];
        int a,b,inc;
        while(t--)
        {
            getchar();
            scanf("%s",cmd);
            if(cmd[0]=='A')
            {
                scanf("%d%d%d",&a,&b,&inc);
                updata(1,a,b,inc);
            }
            else 
            {
                scanf("%d",&a);
                query(1,a);
            }
        }
    //    system("pause");
        return 0;
    }
    

      

    解决方案二:树状数组,由于树状数组就是解决插入一个点查询区间和或者插入一个区间查询一个点的问题的,所以相比线段树更简洁,更高效

     
    #include <iostream>
    #include <cstdio>
    using namespace std;
    const int N=1000005;
    int c[N];
    int m;
    int lowbit(int n)
    {
        return n&(-n);
    }
    int get(int n)
    {
        int sum=0;
        while(n<m)
        {
            sum+=c[n];
            n+=lowbit(n);
        }
        return sum;
    }
    void add(int n,int inc)
    {
        while(n>0)
        {
            c[n]+=inc;
            n-=lowbit(n);
        }
    }
    int main()
    {
        int t;
        scanf("%d%d",&t,&m);
        char cmd[10];
        int a,b,inc;
        while(t--)
        {
            getchar();
            scanf("%s",cmd);
            if(cmd[0]=='A')
            {
                scanf("%d%d%d",&a,&b,&inc);
                add(a-1,-inc);
                add(b,inc);
            }
            else 
            {
                scanf("%d",&a);
                printf("%d\n",get(a));
            }
        }
     //   system("pause");
        return 0;
    }
            
    

      

  • 相关阅读:
    java8 新特性
    class类加载机制
    redis和memcache的区别
    Nginx,Apache,Tomcat区别
    java synchronized锁的理解
    java BIO,NIO在单服务器,多客户端通信上的应用
    理解spring任务调度timer,Quartz,spring task
    理解同步与异步,及java中实现同步机制的方法
    java范型的理解
    正向代理,反向代理的理解
  • 原文地址:https://www.cnblogs.com/hpustudent/p/2129638.html
Copyright © 2020-2023  润新知