首页 > 代码库 > FOJ 2171 防守阵地 II 区间求和区间查询 线段树

FOJ 2171 防守阵地 II 区间求和区间查询 线段树

题目链接:http://acm.fzu.edu.cn/problem.php?pid=2171

题意:

给定n长序列,常数m,q个询问

对于每个询问x

1、求[x, x+m-1] 区间和

2、[x,x+m-1]区间的所有元素-1

线段树裸题,不知为何全用longlong会re,只能改成部分longlong

#include<stdio.h>
#include<string.h>
#define ll long long
#define LL int
#define L(x) (x*2)
#define R(x) (x*2+1)
#define N 100100
LL Mid(LL a,LL b){return (a+b)/2;}
struct node{
	LL l, r;
	ll sum, val;
	ll size(){return (ll)r-(ll)l+1;}
}tree[N*4];
ll a[N];
void push_up(LL x){
	tree[x].val = tree[L(x)].val + tree[R(x)].val;
}
void push_down(LL id){
	if(tree[id].sum){
		tree[L(id)].sum += tree[id].sum;
		tree[R(id)].sum += tree[id].sum;
		tree[L(id)].val += tree[id].sum*tree[L(id)].size();
		tree[R(id)].val += tree[id].sum*tree[R(id)].size();
		tree[id].sum = 0;
	}
}
void build(LL l, LL r, LL id){
	tree[id].l = l, tree[id].r = r; tree[id].sum = 0;
	if(l==r){tree[id].val = a[l]; return;}
	LL mid = Mid(l,r);
	build(l,mid,L(id));
	build(mid+1,r,R(id));
	push_up(id);
}
ll query(LL l, LL r, LL id){
	if(l == tree[id].l && tree[id].r == r)return tree[id].val;
	push_down(id);

	LL mid = Mid(tree[id].l, tree[id].r);
	if(r <= mid)return query(l,r,L(id));
	else if(mid < l)return query(l, r, R(id));
	return query(l,mid,L(id))+query(mid+1,r,R(id));
}
void updata(LL l, LL r, LL id){
	if(l == tree[id].l && tree[id].r == r){
		tree[id].val -= tree[id].size();
		tree[id].sum --;
		return;
	}
	push_down(id);
	LL mid = Mid(tree[id].l, tree[id].r);
	if(r <= mid)updata(l,r,L(id));
	else if(mid < l)updata(l, r, R(id));
	else
	{
		updata(l,mid,L(id));
		updata(mid+1,r,R(id));
	}
	push_up(id);
}
int main(){
	LL n, m, q, i, j, u, v;
	while(~scanf("%d %d %d",&n,&m,&q)){
		for(i=1;i<=n;i++)scanf("%lld",&a[i]);
		build(1,n,1);
		while(q--){
			scanf("%d",&u);	v = u+m-1;
			printf("%lld\n",query(u,v,1));
			updata(u,v,1);
		}
	}
	return 0;
}
/*
5 5 33
2 1 3 1 4
1
1
1
1
1
1

*/