题目链接: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
时间: 2024-10-29 02:42:30