HHUOJ 1405 区间查询

六月ゝ 毕业季﹏ 提交于 2019-11-26 17:30:00

HHUOJ 1405 区间查询

题目描述

食堂有N个打饭窗口,现在正到了午饭时间,每个窗口都排了很多的学生,而且每个窗口排队的人数在不断的变化。
现在问你第i个窗口到第j个窗口一共有多少人在排队?

输入

输入的第一行是一个整数T,表示有T组测试数据。
每组输入的第一行是一个正整数N(N<=30000),表示食堂有N个窗口。
接下来一行输入N个正整数,第i个正整数ai表示第i个窗口最开始有ai个人排队。(1<=ai<=50)
接下来每行有一条命令,命令有四种形式:
(1)Add i j,i和j为正整数,表示第i个窗口增加j个人(j不超过30);
(2)Sub i j,i和j为正整数,表示第i个窗口减少j个人(j不超过30);
(3)Query i j,i和j为正整数,i<=j,表示询问第i到第j个窗口的总人数;
(4)End 表示结束,这条命令在每组数据最后出现;
每组数据最多有40000条命令。

输出

对于每组输入,首先输出样例号,占一行。
然后对于每个Query询问,输出一个整数,占一行,表示询问的段中的总人数,这个数保持在int以内。

样例输入

1
10
1 2 3 4 5 6 7 8 9 10
Query 1 3
Add 3 6
Query 2 7
Sub 10 2
Add 6 3
Query 3 10
End

样例输出

Case 1:
6
33
59

在这里插入图片描述
我用线段树和树状数组都做了一下,线段树759ms,树状数组479ms,放上代码对比一下:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

int tree[120005];

void pushup(int i)
{
     tree[i]=tree[2*i]+tree[2*i+1];
}

void build(int i,int l,int r)
{
    if(l==r)
    {
        scanf("%d",&tree[i]);
        return ;
    }
    int mid=l+(r-l)/2;
    build(2*i,l,mid);
    build(2*i+1,mid+1,r);
    pushup(i);
}

void add(int i,int l,int r,int x,int k)
{
     if(l==r && r==x)
     {
         tree[i]+=k;
         return ;
     }
     int mid=l+(r-l)/2;
     if(x<=mid) add(2*i,l,mid,x,k);
     else add(2*i+1,mid+1,r,x,k);
     pushup(i);
}

void sub(int i,int l,int r,int x,int k)
{
     if(l==r && r==x)
     {
         tree[i]-=k;
         return ;
     }
     int mid=l+(r-l)/2;
     if(x<=mid) sub(2*i,l,mid,x,k);
     else sub(2*i+1,mid+1,r,x,k);
     pushup(i);
}

int query(int i,int l,int r,int x,int y)
{
    if(x<=l && r<=y) return tree[i];
    int ans=0,mid=l+(r-l)/2;
    if(x<=mid) ans+=query(2*i,l,mid,x,y);
    if(y>mid) ans+=query(2*i+1,mid+1,r,x,y);
    return ans;
}

int main()
{
    string s;
    int t,n,x,y;
    scanf("%d",&t);
    for (int i=1;i<=t;i++)
    {
        printf("Case %d:\n",i);
        scanf("%d",&n);
        build(1,1,n);
        while(true)
        {
            cin>>s;
            if(s=="End") break;
           if(s=="Query")
         {
            scanf("%d%d",&x,&y);
            printf("%d\n",query(1,1,n,x,y));
         }
         else if (s=="Add")
            {
              scanf("%d%d",&x,&y);
              add(1,1,n,x,y);
            }
         else  if(s=="Sub")
             {
              scanf("%d%d",&x,&y);
              sub(1,1,n,x,y);
             }
         }
    }
    return 0;
}
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int bit[30005],a[30005];
int t,n,x,y;

int lowbit(int x)
{
    return x&(-x);
}

void add(int i,int x)
{
     while(i<=n)
     {
         bit[i]+=x;
         i+=lowbit(i);
     }
}

void sub(int i,int x)
{
    while(i<=n)
    {
        bit[i]-=x;
        i+=lowbit(i);
    }
}

int sum(int i)
{
     int s=0;
     while(i>0)
     {
         s+=bit[i];
         i-=lowbit(i);
     }
     return s;
}

int main()
{
    scanf("%d",&t);
    for(int j=1;j<=t;j++)
    {
        memset(a,0,sizeof(a));//一定要memset,否则WA
        memset(bit,0,sizeof(bit));
        printf("Case %d:\n",j);
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
            add(i,a[i]);
        }
    string s;
    while(cin>>s)
    {
        if(s=="End") break;
        else if(s=="Add") {scanf("%d%d",&x,&y); add(x,y);}
        else if(s=="Sub") {scanf("%d%d",&x,&y); sub(x,y);}
        else if(s=="Query") {scanf("%d%d",&x,&y); printf("%d\n",sum(y)-sum(x-1));}
    }
  }
 return 0;
}
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!