LightOj 1112 Curious Robin Hood(线段树||树状数组)

Curious
Robin Hood

Robin Hood likes to loot rich people since he helps the poor people with this money. Instead of keeping all the money together he does another trick. He keeps n sacks where he keeps this money. The sacks are numbered from 0 to n-1.

Now each time he can he can do one of the three tasks.

1)                  Give all the money of the ith sack to the poor, leaving the sack empty.

2)                  Add new amount (given in input) in the ith sack.

3)                  Find the total amount of money from ith sack to jth sack.

Since he is not a programmer, he seeks your help.

Input starts with an integer T (≤ 5), denoting the number of test cases.

Each case contains two integers n (1 ≤ n ≤ 105) and q (1 ≤ q ≤ 50000). The next line contains n space separated integers in the range [0, 1000]. The ith integer
denotes the initial amount of money in the ith sack (0 ≤ i < n).

Each of the next q lines contains a task in one of the following form:

1 i        Give all the money of the ith(0 ≤ i < n) sack to the poor.

2 i v     Add money v (1 ≤ v ≤ 1000) to the ith(0 ≤ i < n) sack.

3 i j      Find the total amount of money from ith sack to jth sack (0 ≤ i ≤ j < n).

For each test case, print the case number first. If the query type is 1,
then print the amount of money given to the poor. If the query type is 3,
print the total amount from ith to jth sack.

1

5 6

3 2 1 4 5

1 4

2 3 4

3 0 3

1 2

3 0 4

1 1

Case 1:

5

14

1

13

2

题意:

输入T组测试数据:

N个数据,Q个操作;

1,i   将编号为i的数变成0,并且输出被改变的点的数值;

2,i,v 将编号为i的数加v;

3,i,j 输出i~j之间的总和;

思路:

线段树或者树状数组直接就over了;

这个题和hdoj 1166 点击打开链接思路基本一样,单点更新

注意点:

这是平时是训练的一道题目,我有点遗憾,就在最后1秒钟想到哪儿错了。。。。。。。

1 ,i  不是直接输出,而是通过query或者getsum求,我把他当成直接输出了

线段树:

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
using namespace std;
#define lson l,mid,v<<1
#define rson mid+1,r,v<<1|1
typedef long long int LL;
const int MAX=100000;
int sum[4*MAX+20];
int num[MAX+5];

void build (int l,int r,int v)
{
	sum[v]=0;
	if(l==r)
	{
	  sum[v]=num[l];
	  return ;
	}
	int mid=(l+r)>>1;
	build(lson);
	build(rson);
	sum[v]=sum[2*v]+sum[2*v+1] ;
}

void update(int l,int r,int v,int pos,int x)
{
	if(l==r)
	{
		sum[v]+=x;
		return ;
	}
	int mid=(l+r)>>1;
	if(pos<=mid)
	update(lson,pos,x);
	else
	update(rson,pos,x);
	sum[v]=sum[2*v]+sum[2*v+1] ;
}

int query(int l,int r,int v,int lpos,int rpos)
{
   if(lpos<=l&&r<=rpos)
    return sum[v];
   int mid=(l+r)>>1;
   if(rpos<=mid)
   return query(lson,lpos,rpos);
   else if(lpos>mid)
   return query(rson,lpos,rpos);
   else
   return query(lson,lpos,mid)+query(rson,mid+1,rpos);
} 

int main()
{
  int T,ca=1;
  scanf("%d",&T);
  while(T--)
  {
   int n,m;
   scanf("%d%d",&n,&m);
   memset(num,0,sizeof(num));
   for(int i=1;i<=n;i++)
    scanf("%d",&num[i]);
   build(1,n,1);

   printf("Case %d:\n",ca++);
   while(m--)
   {
   	int opr;
   	int a=0,b=0,c=0;
    scanf("%d",&opr);
      if(opr==1)
      {
   	    scanf("%d",&a);
   	    a++;
   	    printf("%d\n",query(1,n,1,a,a));//这儿坑爹
	    update(1,n,1,a,-query(1,n,1,a,a));//注意
      }
      if(opr==2)
      {
	 scanf("%d%d",&a,&b);
	 a++;
	 update(1,n,1,a,b);

      }
      if(opr==3)
      {
	 scanf("%d%d",&a,&b);
	 a++;b++;
	 printf("%d\n",query(1,n,1,a,b));
     }
   }
  }
return 0;
}

树状数组:

#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long int LL;
LL num[500001];
int v[500001];
int n;

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

LL getsum(int i)
{
    int sum=0;
    while(i>0)
    {
    sum+=num[i];
     i-=lowbit(i);
    }
    return sum;
}

void update(int i,int m)
{
  while(i<=n)
  {
      num[i]+=m;
      i+=lowbit(i);
  }
}

int main()
{
    int T,ca=1;
    scanf("%d",&T);
    while(T--)
    {
      int m;
	  scanf("%d%d",&n,&m);
      int i,x;
      memset(num,0,sizeof(num));
      for(i=1;i<=n;i++)
      {
        scanf("%d",&v[i]);
        update(i,v[i]);
      }

	  printf("Case %d:\n",ca++);
      while(m--)
      {
        int opr;
        scanf("%d",&opr);
		int l,r;
        if(opr==1)
         {
         	scanf("%d",&l);
         	l++;
         	printf("%d\n",getsum(l)-getsum(l-1));//注意
		update(l,getsum(l-1)-getsum(l)) ;//注意
	 }
        if(opr==2)
        {
          scanf("%d%d",&l,&r);
          l++,r;
          update(l,r);
	}
	if(opr==3)
	{
	  scanf("%d%d",&l,&r);
	   l++;r++;
	    printf("%d\n",getsum(r)-getsum(l-1));
	}
      }
    }
    return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-08-25 19:42:09

LightOj 1112 Curious Robin Hood(线段树||树状数组)的相关文章

Lightoj 1112 - Curious Robin Hood 【单点改动 + 单点、 区间查询】【树状数组 水题】

1112 - Curious Robin Hood PDF (English) Statistics Forum Time Limit: 1 second(s) Memory Limit: 64 MB Robin Hood likes to loot rich people since he helps the poor people with this money. Instead of keeping all the money together he does another trick.

Lightoj 1112 - Curious Robin Hood 【单点修改 + 单点、 区间查询】【树状数组 水题】

1112 - Curious Robin Hood PDF (English) Statistics Forum Time Limit: 1 second(s) Memory Limit: 64 MB Robin Hood likes to loot rich people since he helps the poor people with this money. Instead of keeping all the money together he does another trick.

LightOJ 1112 Curious Robin Hood (单点更新+区间求和)

http://lightoj.com/volume_showproblem.php?problem=1112 题目大意: 1 i        将第i个数值输出,并将第i个值清0 2 i v     将第i个数值加v 3 i j      输出从i到j的数值和 简单的单点更新+区间求和,代码很简单的模板 但此题有一个神坑的地方当操作为1是输出第i个数值不是直接输出,而是通过查找输出(太坑了...) #include<stdio.h> #include<string.h> #incl

Light oj 1112 - Curious Robin Hood【单点更新】

1112 - Curious Robin Hood    PDF (English) Statistics Forum Time Limit: 1 second(s) Memory Limit: 64 MB Robin Hood likes to loot rich people since he helps the poor people with this money. Instead of keeping all the money together he does another tri

Curious Robin Hood(树状数组+线段树)

1112 - Curious Robin Hood    PDF (English) Statistics Forum Time Limit: 1 second(s) Memory Limit: 64 MB Robin Hood likes to loot rich people since he helps the poor people with this money. Instead of keeping all the money together he does another tri

线段树&amp;数状数组

线段树 单点修改,区间查询 #include<bits/stdc++.h> using namespace std; int n,q; long long num[1000010]; struct tree { int l,r; long long sum,max; }t[4000010]; void BuildTree(int,int,int); void Update(int,int,int,int,long long); long long Query(int,int,int,int,i

LightOJ 1085(树状数组+离散化+DP,线段树)

All Possible Increasing Subsequences Time Limit:3000MS     Memory Limit:65536KB     64bit IO Format:%lld & %llu Appoint description: Description An increasing subsequence from a sequence A1, A2 ... An is defined by Ai1, Ai2 ... Aik, where the followi

Vijos P1066 弱弱的战壕【多解,线段树,暴力,树状数组】

弱弱的战壕 描述 永恒和mx正在玩一个即时战略游戏,名字嘛~~~~~~恕本人记性不好,忘了-_-b. mx在他的基地附近建立了n个战壕,每个战壕都是一个独立的作战单位,射程可以达到无限(“mx不赢定了?!?”永恒[email protected][email protected]). 但是,战壕有一个弱点,就是只能攻击它的左下方,说白了就是横纵坐标都不大于它的点(mx:“我的战壕为什么这么菜”ToT).这样,永恒就可以从别的地方进攻摧毁战壕,从而消灭mx的部队. 战壕都有一个保护范围,同它的攻击

浅谈二维中的树状数组与线段树

一般来说,树状数组可以实现的东西线段树均可胜任,实际应用中也是如此.但是在二维中,线段树的操作变得太过复杂,更新子矩阵时第一维的lazy标记更是麻烦到不行. 但是树状数组在某些询问中又无法胜任,如最值等不符合区间减法的询问.此时就需要根据线段树与树状数组的优缺点来选择了. 做一下基本操作的对比,如下图. 因为线段树为自上向下更新,从而可以使用lazy标记使得矩阵的更新变的高校起来,几个不足就是代码长,代码长和代码长. 对于将将矩阵内元素变为某个值,因为树状数组自下向上更新,且要满足区间加法等限制