题目链接: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
*/FOJ 2171 防守阵地 II 区间求和区间查询 线段树,码迷,mamicode.com
原文地址:http://blog.csdn.net/acmmmm/article/details/24598503