HUU1166(敌兵布阵)

题目地址:敌兵布阵

题目大意:

     中文题目。

解题思路:

    简单的线段树,更新节点,区间求和。

    (关于线段数的模板,代码注释很详细)

代码:

  1 #include <algorithm>
  2 #include <iostream>
  3 #include <sstream>
  4 #include <cstdlib>
  5 #include <cstring>
  6 #include <cstdio>
  7 #include <string>
  8 #include <bitset>
  9 #include <vector>
 10 #include <queue>
 11 #include <stack>
 12 #include <cmath>
 13 #include <list>
 14 //#include <map>
 15 #include <set>
 16 using namespace std;
 17 /***************************************/
 18 #define ll long long
 19 #define int64 __int64
 20 #define PI 3.1415927
 21 /***************************************/
 22 const int INF = 0x7f7f7f7f;
 23 const double eps = 1e-8;
 24 const double PIE=acos(-1.0);
 25 const int d1x[]= {0,-1,0,1};
 26 const int d1y[]= {-1,0,1,0};
 27 const int d2x[]= {0,-1,0,1};
 28 const int d2y[]= {1,0,-1,0};
 29 const int fx[]= {-1,-1,-1,0,0,1,1,1};
 30 const int fy[]= {-1,0,1,-1,1,-1,0,1};
 31 const int dirx[]= {-1,1,-2,2,-2,2,-1,1};
 32 const int diry[]= {-2,-2,-1,-1,1,1,2,2};
 33 /*vector <int>map[N];map[a].push_back(b);int len=map[v].size();*/
 34 /***************************************/
 35 void openfile()
 36 {
 37     freopen("data.in","rb",stdin);
 38     freopen("data.out","wb",stdout);
 39 }
 40 priority_queue<int> qi1;
 41 priority_queue<int, vector<int>, greater<int> >qi2;
 42 /**********************华丽丽的分割线,以上为模板部分*****************/
 43 const int M=50010;
 44 struct tree
 45 {
 46     int sum;  //该区间的总和
 47     int left,right;  //记录区间的左右闭区间坐标
 48 } node[M*4];  //需开四倍的空间大小
 49 int p[M];  //储存每个地点的人数数量
 50 int cnt;
 51 void build__tree(int id,int l,int r)  //建树
 52 {
 53     int mid=(l+r)/2;
 54     node[id].left=l;   //初始化赋值区间的坐标
 55     node[id].right=r;
 56     if (l==r)
 57     {
 58         node[id].sum=p[l];  //初始化区间节点的val值
 59         return ;
 60     }
 61     build__tree(id*2,l,mid);  //左孩子
 62     build__tree(id*2+1,mid+1,r); //右孩子
 63     node[id].sum=node[id*2].sum+node[id*2+1].sum;  //通过递归将各个区间节点val更新
 64 }
 65 int query(int id,int l,int r)  //查询区间的总和
 66 {
 67     int mid=(node[id].left+node[id].right)/2;
 68     if (node[id].left==l&&node[id].right==r)
 69         cnt+=node[id].sum;  //找到完全覆盖的区间将该区间的val加和。
 70     else if (l>mid)   //[l,r]在右孩子部分
 71         query(id*2+1,l,r);
 72     else if (r<=mid) // [l,r]在左孩子部分
 73         query(id*2,l,r);
 74     else  //[l,r]区间,左右孩子都有分别递归。
 75     {
 76         query(id*2,l,mid);
 77         query(id*2+1,mid+1,r);
 78     }
 79 }
 80 void updata(int id,int pos,int val)  //从上向下寻找节点,找到节点后然后从下往上更新节点的val值
 81 {
 82     if (node[id].left==pos&&node[id].right==pos)//找到该节点
 83     {
 84         node[id].sum+=val;
 85         return ;
 86     }
 87     int mid=(node[id].left+node[id].right)/2;
 88     if (pos<=mid)  //节点在左孩子部分
 89         updata(id*2,pos,val);
 90     else //节点在右孩子部分
 91         updata(id*2+1,pos,val);
 92     node[id].sum=node[id*2].sum+node[id*2+1].sum; //从下往上更新区间节点的值
 93 }
 94 int main()
 95 {
 96     int cas;
 97     scanf("%d",&cas);
 98     int n;
 99     char s[10];
100     int flag=0;
101     while(cas--)
102     {
103         int i,j;
104         scanf("%d",&n);
105         for(i=1; i<=n; i++)
106             scanf("%d",&p[i]);
107         build__tree(1,1,n);
108         printf("Case %d:
",++flag);
109         while(scanf("%s",s)!=EOF)
110         {
111             int x,y;
112             if (s[0]=='Q')
113             {
114                 scanf("%d%d",&x,&y);
115                 cnt=0;
116                 query(1,x,y);
117                 printf("%d
",cnt);
118             }
119             else if (s[0]=='A')
120             {
121                 scanf("%d%d",&x,&y);
122                 updata(1,x,y);
123             }
124             else if (s[0]=='S')
125             {
126                 scanf("%d%d",&x,&y);
127                 updata(1,x,-y);
128             }
129             else
130                 break;
131         }
132     }
133     return 0;
134 }
View Code
原文地址:https://www.cnblogs.com/ZhaoPengkinghold/p/4005747.html