标签:
南将军麾下有百万精兵,现已知共有M个士兵,编号为1~M,每次有任务的时候,总会有一批编号连在一起人请战(编号相近的人经常在一块,相互之间比较熟悉),最终他们获得的军功,也将会平分到每个人身上,这样,有时候,计算他们中的哪一个人到底有多少军功就是一个比较困难的事情,军师小工的任务就是在南将军询问他某个人的军功的时候,快速的报出此人的军功,请你编写一个程序来帮助小工吧。
假设起始时所有人的军功都是0.
4 10 ADD 1 3 10 QUERY 3 ADD 2 6 50 QUERY 3
10 60
当看到是区间更新的时候 就想到再用士兵杀敌(二)区间查询单点更新的方法不行了
肯定会超时 因为以前好像做过一个懒惰标记的线段树 具体也忘记了
总之算是有了思路
1.在区间更新数据的时候 只要找到区间即可 无需找到具体的位置
2.查询的时候要一搜到底。
这道题对比着士兵杀敌(二)区间查询单点更新 还是很容易理解的
代码:
#include <stdio.h> struct node { int left,right; long long num; }tree[1000000*4]; //初始化线段树 void build(int left,int right,int root) { tree[root].left=left; tree[root].right=right; if(left==right) { tree[root].num=0; return ; } else { int mid=(left+right)>>1; build(left,mid,root*2); build(mid+1,right,root*2+1); tree[root].num=0; } } //更新区间值 void update(int l,int r,int x,int root) { //找到对应区间即可 if(tree[root].left==l&&tree[root].right==r) { tree[root].num+=x; return ; } int mid=(tree[root].left+tree[root].right)>>1; if(mid<l) update(l,r,x,root*2+1); else if(mid>=r) update(l,r,x,root*2); else { update(l,mid,x,root*2); update(mid+1,r,x,root*2+1); } } //从根到叶子 一搜到底 void search(int root,int pos,long long &result) { if(tree[root].left==tree[root].right&&tree[root].left==pos) { result+=tree[root].num; return ; } int mid=(tree[root].left+tree[root].right)>>1; if(pos>mid) search(root*2+1,pos,result); else search(root*2,pos,result); result+=tree[root].num; } int main() { int n,k; scanf("%d %d",&k,&n); build(1,n,1); for(int i=0;i<k;i++) { char str[20]; scanf("%s",str); if(str[0]=='A') { int a,b,x; scanf("%d %d %d",&a,&b,&x); update(a,b,x,1); } if(str[0]=='Q') { int pos; long long result=0; scanf("%d",&pos); search(1,pos,result); printf("%d\n",result); } } return 0; }
nyoj 116 士兵杀敌(四)(线段树区间更新和单点查询)
标签:
原文地址:http://blog.csdn.net/su20145104009/article/details/51149635