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;
    }

  • 相关阅读:
    -bash: fork: Cannot allocate memory 问题的处理
    Docker top 命令
    docker常见问题修复方法
    The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!)
    What's the difference between encoding and charset?
    hexcode of é î Latin-1 Supplement
    炉石Advanced rulebook
    炉石bug反馈
    Sidecar pattern
    SQL JOIN
  • 原文地址:https://www.cnblogs.com/java20130726/p/3218167.html
Copyright © 2011-2022 走看看