FZU2171 防守阵地 II(线段树)

 Problem 2171 防守阵地 II

Accept: 298    Submit: 1119
Time Limit: 3000 mSec    Memory Limit : 32768 KB

 Problem Description

部队中总共有N个士兵,每个士兵有各自的能力指数Xi,在一次演练中,指挥部确定了M个需要防守的地点,指挥部将选择M个士兵依次进入指定地点进行防守任务,获得的参考指数即为M个士兵的能力之和。随着时间的推移,指挥部将下达Q个指令来替换M个进行防守的士兵们,每个参加完防守任务的士兵由于疲惫等原因能力指数将下降1。现在士兵们排成一排,请你计算出每次进行防守的士兵的参考指数。

 Input

输入包含多组数据。

输入第一行有两个整数N,M,Q(1<=N<=100000,1<=M<=1000,1<=Q<=100000),第二行N个整数表示每个士兵对应的能力指数Xi(1<=Xi<=1000)。

接下来Q行,每行一个整数X,表示在原始队列中以X为起始的M个士兵替换之前的士兵进行防守。(1<=X<=N-M+1)

对于30%的数据1<=M,N,Q<=1000。

 Output

输出Q行,每行一个整数,为每次指令执行之后进行防守的士兵参考指数。

 Sample Input

5 3 32 1 3 1 4123

 Sample Output

635



题目链接:点击打开链接

线段树的模板题, 每次询问过后士兵能力指数减1.

AC代码:

#include "iostream"
#include "cstdio"
#include "cstring"
#include "algorithm"
#include "queue"
#include "stack"
#include "cmath"
#include "utility"
#include "map"
#include "set"
#include "vector"
#include "list"
#include "string"
using namespace std;
typedef long long ll;
const int MOD = 1e9 + 7;
const int INF = 0x3f3f3f3f;
const int MAXN = 1e5 + 5;
#define root 1, n, 1
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1 | 1
int n, m, q, L, R, sum[MAXN << 2], add[MAXN << 2];
void push_up(int rt)
{
	sum[rt] = sum[rt << 1] + sum[rt << 1 | 1];
}
void push_down(int l, int r, int rt)
{
	if(add[rt] ) {
		int m = (l + r) >> 1;
		add[rt << 1] += add[rt] ;
		sum[rt << 1] -= add[rt] * (m - l + 1);
		add[rt << 1 | 1] += add[rt];
		sum[rt << 1 | 1] -= add[rt] * (r - m);
		add[rt] = 0;
	}
}
void build(int l, int r, int rt)
{
	add[rt] = 0;
	if(l == r) {
		scanf("%d", &sum[rt]);
		return;
	}
	int m = (l + r) >> 1;
	build(lson);
	build(rson);
	push_up(rt);
}
void update(int l, int r, int rt)
{
	if(L <= l && r <= R) {
		add[rt]++;
		sum[rt] -= r - l + 1;
		return;
	}
	push_down(l, r, rt);
	int m = (l + r) >> 1;
	if(L <= m) update(lson);
	if(m < R) update(rson);
	push_up(rt);
}
int query(int l, int r, int rt)
{
	if(L <= l && r <= R) return sum[rt];
	push_down(l, r, rt);
	int m = (l + r) >> 1, ans = 0;
	if(L <= m) ans += query(lson);
	if(m < R) ans += query(rson);
	return ans;
}
int main(int argc, char const *argv[])
{
	while(scanf("%d%d%d", &n, &m, &q) != EOF) {
		build(root);
		while(q--) {
			scanf("%d", &L);
			R = L + m - 1;
			printf("%d\n", query(root));
			update(root);
		}
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值