有关树的知识点(1)

来源:互联网 发布:mac air 能玩什么游戏 编辑:程序博客网 时间:2024/06/04 00:46


可以用以下的模板解决一系列的问题:


模板如下:


#include<cstdio>#include<algorithm>using namespace std;#define L o<<1#define R (o<<1)|1struct Node{int l,r,sum,Max,Min;}Tree[1000<<2];void PushUp(int o){Tree[o].sum = Tree[o*2].sum + Tree[o*2+1].sum;Tree[o].Max = max(Tree[o*2].Max,Tree[o*2+1].Max);Tree[o].Min = min(Tree[o*2].Min,Tree[o*2+1].Min);}void Build(int o,int l,int r){//首先记录l和r的值 Tree[o].l = l;Tree[o].r = r;if (l == r)//到达最底层,递归终止{int t;scanf ("%d",&t);//输入数据 Tree[o].sum = Tree[o].Max = Tree[o].Min = t;//更新节点数据 return;}int mid = (l+r) >> 1;//找到中间节点 Build(o*2 , l , mid);//递归建左子树 Build(o*2+1 , mid+1 , r);//递归建右子树 PushUp(o);//更新当前节点的值 }void UpDate(int o,int l,int r,int x,int y)//把x节点更新为y{if (l == r)//递归结束{Tree[o].Max = Tree[o].Min = Tree[o].sum = y;//精确找到了节点,更新 return;}int mid = (l+r) / 2;//找到中间位置if (x <= mid)UpDate(o*2,l,mid,x,y);//找左子树 elseUpDate(o*2+1,mid+1,r,x,y);//找右子树 PushUp(o);//更新当前节点 }int main(){int n;scanf ("%d",&n);Build(1,1,n);UpDate(1,1,n,2,7);return 0;}


下面举一个例子:


点击打开链接


士兵杀敌(二)

时间限制:1000 ms  |  内存限制:65535 KB
难度:5
描述

南将军手下有N个士兵,分别编号1到N,这些士兵的杀敌数都是已知的。

小工是南将军手下的军师,南将军经常想知道第m号到第n号士兵的总杀敌数,请你帮助小工来回答南将军吧。

南将军的某次询问之后士兵i可能又杀敌q人,之后南将军再询问的时候,需要考虑到新增的杀敌数。

输入
只有一组测试数据
第一行是两个整数N,M,其中N表示士兵的个数(1<N<1000000),M表示指令的条数。(1<M<100000)
随后的一行是N个整数,ai表示第i号士兵杀敌数目。(0<=ai<=100)
随后的M行每行是一条指令,这条指令包含了一个字符串和两个整数,首先是一个字符串,如果是字符串QUERY则表示南将军进行了查询操作,后面的两个整数m,n,表示查询的起始与终止士兵编号;如果是字符串ADD则后面跟的两个整数I,A(1<=I<=N,1<=A<=100),表示第I个士兵新增杀敌数为A.
输出
对于每次查询,输出一个整数R表示第m号士兵到第n号士兵的总杀敌数,每组输出占一行
样例输入
5 61 2 3 4 5QUERY 1 3ADD 1 2QUERY 1 3ADD 2 3QUERY 1 2QUERY 1 5
样例输出
68820




AC  代码如下:



#include<stdio.h>  #include<stdlib.h>  #include<string.h>  #define N 1000010  int w[N];  struct{      long long value,add;      int left,right;  }Tire[2500000];  void Build(int p,int left,int right){      int mid=(left+right)>>1;      int v=p<<1;      Tire[p].left=left;      Tire[p].right=right;      Tire[p].add=0;      if(left==right)      {          Tire[p].value=w[left];          return ;      }      Build(v,left,mid);      Build(v+1,mid+1,right);      Tire[p].value=Tire[v].value+Tire[v+1].value;  }  void update(int p,int left,int right,long long add){      int mid=(Tire[p].left+Tire[p].right)>>1;      int v=p<<1;      if(Tire[p].left==left&&Tire[p].right==right)      {          Tire[p].add+=add;          return ;//递归出口      }      Tire[p].value+=(right-left+1)*add;      if(right<=mid)         update(v,left,right,add);      else if(left>=mid+1)         update(v+1,left,right,add);      else      {          update(v,left,mid,add);          update(v+1,mid+1,right,add);      }  }  long long query(int p,int left,int right){      int mid=(Tire[p].left+Tire[p].right)>>1;      int v=p<<1;      if(Tire[p].left==left&&Tire[p].right==right)      return Tire[p].value+(Tire[p].right-Tire[p].left+1)*Tire[p].add;      else      {//增量下移           Tire[v].add+=Tire[p].add;          Tire[v+1].add+=Tire[p].add;          Tire[p].value+=(Tire[p].right-Tire[p].left+1)*Tire[p].add;          Tire[p].add=0;      }//else      if(right<=mid)      return query(v,left,right);      if(left>=mid+1)      return query(v+1,left,right);      return query(v,left,mid)+query(v+1,mid+1,right);  }   int main()  {      int n,p,i,a,b;      char s[10];       while(scanf("%d %d",&n,&p)!=EOF)      {          for(i=1;i<=n;i++)          scanf("%d",&w[i]);          Build(1,1,n);//构建线段树          for(i=1;i<=p;i++)          {              scanf("%s",s);              if(strcmp(s,"QUERY")==0)              {                  scanf("%d %d",&a,&b);                  printf("%I64d\n",query(1,a,b));              }              else              {                  scanf("%d %d",&a,&b);                  update(1,a,a,b);              }          }//for      }//while     // system("pause");      return 0;  }  





原创粉丝点击