HDU 6315 Naive Operations <<线段树

题意

在一个数据结构上实现区间加一,询问区间内$a_i/b_i$的和,$b_i$是事先给出的一个序列

思路

线段树维护区间最小值与区间和,区间最小值维护$a_i$序列,每次加操作区间最小值减一,如果最小值减到零,就去暴力更新区间和,区间和维护的是答案的和。

代码

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 const int maxn=1e5+7;
  4 struct node{
  5     int b,low,sum;
  6 }sgt[maxn*4];
  7 int lazy[maxn*4];
  8 void pushup(int rt)
  9 {
 10     sgt[rt].low=min(sgt[rt*2].low,sgt[rt*2+1].low);
 11     sgt[rt].sum=sgt[rt*2].sum+sgt[rt*2+1].sum;
 12 }
 13 void pushdown(int L,int R,int rt)
 14 {
 15     if(lazy[rt])
 16     {
 17         sgt[rt*2].low-=lazy[rt];
 18         sgt[rt*2+1].low-=lazy[rt];
 19         lazy[rt*2]+=lazy[rt];
 20         lazy[rt*2+1]+=lazy[rt];
 21         lazy[rt]=0;
 22     }
 23     if(sgt[rt].low<=0)
 24     {
 25         if(L==R)
 26         {
 27             while(sgt[rt].low<=0)
 28             {
 29                 sgt[rt].low+=sgt[rt].b;
 30                 sgt[rt].sum++;
 31             }
 32             return;
 33         }
 34         int mid=L+R>>1;
 35         pushdown(L,mid,rt*2);
 36         pushdown(mid+1,R,rt*2+1);
 37         pushup(rt);
 38     }
 39 }
 40 void build(int l,int r,int rt)
 41 {
 42     if(l==r)
 43     {
 44         scanf("%d",&sgt[rt].b);
 45         sgt[rt].low=sgt[rt].b;
 46         return;
 47     }
 48     int mid=l+r>>1;
 49     build(l,mid,rt*2);
 50     build(mid+1,r,rt*2+1);
 51     pushup(rt);
 52 }
 53 void update(int l,int r,int L,int R,int rt)
 54 {
 55     pushdown(L,R,rt);
 56     if(L>=l&&R<=r)
 57     {
 58         sgt[rt].low-=1;
 59         lazy[rt]+=1;
 60         return ;
 61     }
 62     int mid=L+R>>1;
 63     if(mid>=l)
 64         update(l,r,L,mid,rt*2);
 65     if(mid<r)
 66         update(l,r,mid+1,R,rt*2+1);
 67     pushup(rt);
 68 }
 69 int query(int l,int r,int L,int R,int rt)
 70 {
 71     pushdown(L,R,rt);
 72     if(L>=l&&R<=r)
 73     {
 74         return sgt[rt].sum;
 75     }
 76     int mid=L+R>>1;
 77     int ret=0;
 78     if(mid>=l)
 79         ret+=query(l,r,L,mid,rt*2);
 80     if(mid<r)
 81         ret+=query(l,r,mid+1,R,rt*2+1);
 82     return ret;
 83 }
 84 int main()
 85 {
 86     int n,q;
 87     while(~scanf("%d%d",&n,&q))
 88     {
 89         memset(sgt,0,sizeof(sgt));
 90         memset(lazy,0,sizeof(lazy));
 91         build(1,n,1);
 92         char op[10];
 93         while(q--)
 94         {
 95             int l,r;
 96             scanf("%s",op);
 97             scanf("%d%d",&l,&r);
 98             if(op[0]=='a')
 99                 update(l,r,1,n,1);
100             else{
101                 int ans=query(l,r,1,n,1);
102                 printf("%d\n",ans);
103             }
104         }
105     }
106 }

后记

还是要学会线段树的灵活运用的!感觉提升了一点对线段树的认识。

posted @ 2018-12-10 12:44  computer_luo  阅读(119)  评论(0编辑  收藏  举报