士兵杀敌(四)
士兵杀敌(四)
时间限制:2000 ms | 内存限制:65535 KB
难度:5
- 描述
-
南将军麾下有百万精兵,现已知共有M个士兵,编号为1~M,每次有任务的时候,总会有一批编号连在一起人请战(编号相近的人经常在一块,相互之间比较熟悉),最终他们获得的军功,也将会平分到每个人身上,这样,有时候,计算他们中的哪一个人到底有多少军功就是一个比较困难的事情,军师小工的任务就是在南将军询问他某个人的军功的时候,快速的报出此人的军功,请你编写一个程序来帮助小工吧。
假设起始时所有人的军功都是0.
- 输入
- 只有一组测试数据。
每一行是两个整数T和M表示共有T条指令,M个士兵。(1<=T,M<=1000000)
随后的T行,每行是一个指令。
指令分为两种:
一种形如
ADD 100 500 55 表示,第100个人到第500个人请战,最终每人平均获得了55军功,每次每人获得的军功数不会超过100,不会低于-100。
第二种形如:
QUERY 300 表示南将军在询问第300个人的军功是多少。 - 输出
- 对于每次查询输出此人的军功,每个查询的输出占一行。
- 样例输入
-
4 10 ADD 1 3 10 QUERY 3 ADD 2 6 50 QUERY 3
- 样例输出
-
10 60
代码: - #include <iostream>
#include<stdio.h>
#define MAX 1000010
using namespace std;
struct node
{
int left,right;
int num;
node()
{
num=0;
}
};
node tree[4*MAX];
void build(int left,int right,int i)
{
tree[i].left=left;tree[i].right=right;
if (left<right)
{
int mid=(left+right)>>1;
build(left,mid,2*i);
build(mid+1,right,2*i+1);
}
}
void insert(int i,int left,int right,int num)
{
if(left<=tree[i].left&&tree[i].right<=right)
{
tree[i].num+=num;
return;
}
if (tree[i].left<tree[i].right)
{
int mid=(tree[i].left+tree[i].right)>>1;
if(right<=mid)
insert(2*i,left,right,num);
else if (left>mid)
insert(2*i+1,left,right,num);
else
{
insert(2*i,left,mid,num);
insert(2*i+1,mid+1,right,num);
}
}
}
int sum;
void finds(int k,int i)
{
if (tree[i].left<=k&&k<=tree[i].right)
{
sum+=tree[i].num;
}
if(tree[i].left<tree[i].right)
{
int mid=(tree[i].left+tree[i].right)>>1;
if(k<=mid)
finds(k,2*i);
else
finds(k,2*i+1);
}
}
int main()
{
int n,t,k,i,num,left,right;
char a[10];
cin>>t>>n;
build(1,n,1);
for(i=0;i<t;i++)
{
scanf("%s",a);
if(a[0]=='A')
{
scanf("%d%d%d",&left,&right,&num);
insert(1,left,right,num);
}
else
{
sum=0;
scanf("%d",&k);
finds(k,1);
printf("%d\n",sum);
}
}
return 0;
}