zoukankan      html  css  js  c++  java
  • hdu 1166 敌兵布阵(线段树-单点更新)

    题意有N个兵营,每个兵营都给出了人数ai(下标从1开始),有四种命令,(1)”Addij",表示第i个营地增加j人。(2)“Sub i j”,表示第i个营地减少j人。(3)“Query ij",查询第i个营地到第j个营地的总人数。(4)”End“,表示命令结束。

    有三种操作:询问区间总和,增加某个兵营的兵的数目,减少某个兵营的兵的数目。实际上也只有两个。

    在更新的时候,每到一个区间就把当前区间的sum增加对应的数目,到达叶子结点是返回。这样就可以不会回溯去更新父亲结点的值。查询的时候,如果区间完全匹配,直接返回区间的sum值,否则向下寻找,直到完全匹配,然后返回它们的和就可以。这时候,结果里保存的边界是它们真正的边界。

    // Time 203ms; Memory 1944K
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define maxn 1<<17
    
    using namespace std;
    
    int size,n,sum,all[40010];
    struct line
    {
        int l,r;
        int n;
    }a[maxn];
    
    void init()
    {
        int i;
        for(n=1;n<size;n<<=1);
        for(i=n;i<2*n;i++) 
        {
            a[i].l=a[i].r=i-n+1;
            a[i].n=0;
        }
        for(i=n-1;i>0;i--)
        {
            a[i].l=a[2*i].l;
            a[i].r=a[2*i+1].r;
            a[i].n=0;
        }
    }
    void insert(int i,int x,int m)
    {
        if(x>=a[i].l && x<=a[i].r) a[i].n+=m;
        if(a[i].l==a[i].r) return;
        int mid=(a[i].l+a[i].r)/2;
        if(x>mid) insert(2*i+1,x,m);
        else insert(2*i,x,m);
    }
    void find(int x,int y,int i)
    {
        if(x==a[i].l && y==a[i].r)
        {
            sum+=a[i].n;
            return;
        }
        if(a[i].l==a[i].r) return;
        int mid=(a[i].l+a[i].r)/2;
        if(x>mid) find(x,y,2*i+1);
        else if(y<=mid) find(x,y,2*i);
        else 
        {
            find(x,mid,2*i);
            find(mid+1,y,2*i+1);
        }
    }
    int main()
    {
        int i,j,k,t,x,y,m;
        char s[7];
        scanf("%d",&t);
        for(i=0;i<t;i++)
        {
            scanf("%d",&size);
            init();
            for(j=0;j<size;j++)
            {
                scanf("%d",&k);
                insert(1,j+1,k);
            }
            k=0;
            while(scanf("%s",s)!=EOF && strcmp(s,"End"))
            {
                if(strcmp(s,"Add")==0)
                {
                    scanf("%d%d",&x,&m);
                    insert(1,x,m);
                }
                else if(strcmp(s,"Sub")==0)
                {
                    scanf("%d%d",&x,&m);
                    insert(1,x,-m);
                }
                else 
                {
                    scanf("%d%d",&x,&y);
                    sum=0;
                    find(x,y,1);
                    all[k++]=sum;
                }
            }
            printf("Case %d:
    ",i+1);
            for(j=0;j<k;j++) printf("%d
    ",all[j]);
        }
        return 0;
    }

  • 相关阅读:
    尖峰冲击测试(spike Testing)
    mysql返回记录的ROWNUM(转)
    SQL2005四个排名函数(row_number、rank、dense_rank和ntile)的比较
    JUnit编写单元测试代码注意点小结
    Linux下Tomcat的启动、关闭、杀死进程
    linux下oracle11g R2的启动与关闭监听、数据库
    linux下使用yum安装mysql详解
    VC++ 实现文件与应用程序关联
    C++ 去掉字符串首尾的 x20 字符
    VC++ 线程同步 总结
  • 原文地址:https://www.cnblogs.com/java20130726/p/3218167.html
Copyright © 2011-2022 走看看