• ll 1164 线段树


    1164 - 战舰萝莉

    Time Limit:2s Memory Limit:256MByte

    Submissions:85Solved:42

    DESCRIPTION

    在大战之后,法力浮·鳝AK迅速驾船驶向北海。当然他知道水之灵不可能那么容易得到,正如爱迪生曾说过:“要把BOSS打倒就要准备足够的等级。”所以鳝氪金招募了一队海盗以防战斗。
    果不其然,正当鳝看见了水之灵的所在时,一大队舰娘(雾),一大队舰船突然闪现,大战一触即发。
    大战前,鳝被对面的boss——北方栖姬吸引了,北方栖姬是一个可爱的小萝莉,实力却很是强劲,而鳝打算把她诱拐回家(雾),打算把她策略击破。
    鳝通过提督的观察,发现北方栖姬摆出了“线段树阵形”,具体是这样的:
    可以将深海栖舰的舰队看作对一个长度为n的序列建成的线段树,线段树的每个节点维护区间和,记作sumv[o]。这个值同时也是该节点的敌舰所具有的火力。同时在作战过程中,北方栖姬会不断发出区间加和区间减的指令,请注意,这些指令是以打标记的形式维护的,换而言之,某些点的sumv可能不会及时更新。
    在每次敌舰队发生变化之后,鳝会问你,当前敌舰队有多少舰是“有威胁”的,我们称一艘舰是有威胁的当且仅当这艘舰的火力>k(一个给定常数)。
    作为鳝船上的一名海盗,您需要回答法力浮鳝的所有询问。
    下面给出敌舰队的建成,修改的具体示例代码:
    http://paste.ubuntu.com/25598285/

    INPUT
    输入的第一行三个整数n,m,k,m表示操作次数。 接下来一行n个整数,表示线段树维护的原序列。 接下来m行,每行四个整数opt,l,r,x 如果opt=1表示区间加,反之则是区间减。表示在[l,r]加上或者减去x
    OUTPUT
    共m行,每行一个整数表示每次操作后的答案。
    SAMPLE INPUT
    8 2 20 1 2 3 4 5 6 7 8 2 1 8 100 1 1 3 20
    SAMPLE OUTPUT
    1 0
    HINT
    1 ≤ n ,m≤ 100000,序列值,k和sumv[o]始终在int范围内,可能出现负数
       A盯了一个小时后发现不会= =再看这道为什么这么水!难道第一题不是签到题- -!
    代码都给出来了,xjb改一下维护一个总值k就好了,在修改函数pushdown里面维护。
     
     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 int a[100005];
     4 int sumv[400005];
     5 int addv[400005];
     6 int ans=0,K;
     7 struct SegTree
     8 {
     9 #define lson (o<<1)
    10 #define rson (o<<1|1)
    11 inline void pushup(int o)
    12 {
    13     int tmp=sumv[lson]+sumv[rson];
    14     if(sumv[o]<=K&&tmp>K) ans++;
    15     if(sumv[o]>K&&tmp<=K) ans--;
    16     sumv[o]=tmp;
    17 }
    18 inline void pushdown(int o,int l,int r){
    19      if(!addv[o]) {return;}
    20      int mid=(l+r)>>1,tag=addv[o];
    21      addv[lson]+=tag;addv[rson]+=tag;
    22      int tmp1=sumv[lson]+tag*(mid-l+1);
    23      int tmp2=sumv[rson]+tag*(r-mid);
    24      if(sumv[lson]<=K&&tmp1>K) ans++;
    25      if(sumv[lson]>K&&tmp1<=K) ans--;
    26      if(sumv[rson]<=K&&tmp2>K) ans++;
    27      if(sumv[rson]>K&&tmp2<=K) ans--;
    28      sumv[lson]=tmp1;
    29      sumv[rson]=tmp2;
    30      addv[o]=0;
    31 }
    32 inline void build(int o,int l,int r){
    33      if(l==r){sumv[o]=a[l];if(sumv[o]>K)ans++;return;}
    34      int mid=(l+r)>>1;
    35      build(lson,l,mid);
    36      build(rson,mid+1,r);
    37      pushup(o);
    38 }
    39 inline void optadd(int o,int l,int r,int ql,int qr,int v){
    40      if(ql<=l&&r<=qr){int tmp=v*(r-l+1);
    41      if(sumv[o]<=K&&sumv[o]+tmp>K) ans++;
    42      if(sumv[o]>K&&sumv[o]+tmp<=K) ans--;
    43      sumv[o]+=tmp;
    44      addv[o]+=v;
    45      return;
    46    }
    47      int mid=(l+r)>>1;
    48      pushdown(o,l,r);
    49      if(ql<=mid)optadd(lson,l,mid,ql,qr,v);
    50      if(qr>mid)optadd(rson,mid+1,r,ql,qr,v);
    51      pushup(o);
    52 }
    53 }seg;
    54 int main()
    55 {
    56     int N,M;
    57     while(scanf("%d%d%d",&N,&M,&K)!=EOF){ans=0;
    58         for(int i=1;i<=N;++i) scanf("%d",a+i);
    59         memset(addv,0,sizeof(addv));
    60         seg.build(1,1,N);//cout<<ans<<endl;
    61         int opt,l,r,x;
    62         while(M--){
    63             scanf("%d%d%d%d",&opt,&l,&r,&x);
    64             if(opt==2) x=-x;
    65             seg.optadd(1,1,N,l,r,x);
    66             printf("%d
    ",ans);
    67         }
    68     }
    69     return 0;
    70 }
  • 相关阅读:
    团队项目 第一次作业
    20165215 实验三 敏捷开发与XP实践
    20165215 2017-2018-2 《Java程序设计》第九周学习总结
    20165204 20165216 20165220 实验一开发化境的熟悉
    20165220 缓冲区溢出漏洞实验
    20165220 《信息安全系统设计基础》第二周学习总结
    2018-2019 信息安全系统设计基础 第一周总结
    20165220 2017-2018-2《Java程序设计》课程总结
    20165220 实验五 网络编程与安全
    20165220Java实验四 Android程序设计
  • 原文地址:https://www.cnblogs.com/zzqc/p/7588621.html
Copyright © 2020-2023  润新知