南将军麾下有百万精兵,现已知共有M个士兵,编号为1~M,每次有任务的时候,总会有一批编号连在一起人请战(编号相近的人经常在一块,相互之间比较熟悉),最终他们获得的军功,也将会平分到每个人身上,这样,有时候,计算他们中的哪一个人到底有多少军功就是一个比较困难的事情,军师小工的任务就是在南将军询问他某个人的军功的时候,快速的报出此人的军功,请你编写一个程序来帮助小工吧。
假设起始时所有人的军功都是0.
4 10 ADD 1 3 10 QUERY 3 ADD 2 6 50 QUERY 3
10 60
区间更新,单点查询,不用lazy
ac代码:
#include<stdio.h> #include<string.h> struct s { int left; int right; int sum; }tree[4000000+1000]; void pushdown(int i) { if(tree[i].sum) { tree[i*2].sum+=tree[i].sum; tree[i*2+1].sum+=tree[i].sum; tree[i].sum=0; } } void build(int l,int r,int i) { int mid; tree[i].left=l; tree[i].right=r; if(l==r) { tree[i].sum=0; return; } mid=(l+r)/2; build(l,mid,i*2); build(mid+1,r,i*2+1); } void add(int l,int r,int c,int i) { int mid; if(tree[i].left==l&&tree[i].right==r) { tree[i].sum+=c; return; } mid=(tree[i].left+tree[i].right)/2; if(r<=mid) add(l,r,c,i*2); else if(l>mid) add(l,r,c,i*2+1); else { add(l,mid,c,i*2); add(mid+1,r,c,i*2+1); } } int query(int a,int i) { int mid; if(tree[i].left<tree[i].right) { pushdown(i);//除最下面的节点外,其他结点的sum都为0 mid=(tree[i].left+tree[i].right)/2; if(a<=mid) return query(a,i*2); if(a>mid) return query(a,i*2+1); } return tree[i].sum; } int main() { int i,n,m; int a,b,c; char ch[10]; scanf("%d%d",&m,&n); build(1,n,1); for(i=0;i<m;i++) { scanf("%s",ch); if(strcmp(ch,"ADD")==0) { scanf("%d%d%d",&a,&b,&c); if(a==0)//看别人说有这个情况 a++; add(a,b,c,1); } if(strcmp(ch,"QUERY")==0) { scanf("%d",&a); printf("%d\n",query(a,1)); } } return 0; }