FZU Problem 2171 防守阵地 II (线段树,区间更新)

 Problem 2171 防守阵地 II

Accept: 143    Submit: 565
Time Limit: 3000 mSec    Memory Limit : 32768 KB

 Problem Description

部队中总共有N个士兵,每个士兵有各自的能力指数Xi,在一次演练中,指挥部确定了M个需要防守的地点,指挥部将选择M个士兵依次进入指定地点进行防守任务,获得的参考指数即为M个士兵的能力之和。随着时间的推移,指挥部将下达Q个指令来替换M个进行防守的士兵们,每个参加完防守任务的士兵由于疲惫等原因能力指数将下降1。现在士兵们排成一排,请你计算出每次进行防守的士兵的参考指数。

 Input

输入包含多组数据。

输入第一行有两个整数N,M,Q(1<=N<=100000,1<=M<=1000,1<=Q<=100000),第二行N个整数表示每个士兵对应的能力指数Xi(1<=Xi<=1000)。

接下来Q行,每行一个整数X,表示在原始队列中以X为起始的M个士兵替换之前的士兵进行防守。(1<=X<=N-M+1)

对于30%的数据1<=M,N,Q<=1000。

 Output

输出Q行,每行一个整数,为每次指令执行之后进行防守的士兵参考指数。

 Sample Input

5 3 3
2 1 3 1 4
1
2
3

 Sample Output

6
3
5

 

线段树区间修改,注意延迟标记,修改函数和查询函数的参数是不能改的啊!

延迟标记:

每个节点新增加一个标记,记录这个节点是否进行了某种修改(这种修改操作会影响其子节点),对于任意区间的修改,我们先按照区间查询的方式将其划分成线段树中的节点,然后修改这些节点的信息,并给这些节点标记上代表这种修改操作的标记。在修改和查询的时候,如果我们到了一个节点p,并且决定考虑其子节点,那么我们就要看节点p是否被标记,如果有,就要按照标记修改其子节点的信息,并且给子节点都标上相同的标记,同时消掉节点p的标记。

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<stdlib.h>
  4 #include<algorithm>
  5 using namespace std;
  6 const int MAXN=100000+10;
  7 int b[MAXN*4];
  8 struct node
  9 {
 10     int l,r;
 11     int num;
 12     int col;
 13     int mid()
 14     {
 15         return (l+r)/2;
 16     }
 17 }a[MAXN*5];
 18 
 19 void pushup(int step)
 20 {
 21     a[step].num=a[step*2].num+a[step*2+1].num;
 22 }
 23 
 24 void pushdown(int x,int step)
 25 {
 26     if(a[step].col!=0)
 27     {
 28         a[step*2+1].col+=a[step].col;
 29         a[step*2].col+=a[step].col;
 30         a[step*2].num+=a[step].col*(x-(x/2));
 31         a[step*2+1].num+=a[step].col*((x/2));
 32         a[step].col=0;
 33     }
 34 }
 35 
 36 void btree(int l,int r,int step)
 37 {
 38     a[step].l=l;
 39     a[step].r=r;
 40     a[step].col=0;
 41     if(l==r)
 42     {
 43         a[step].num=b[l];
 44         return ;
 45     }
 46     int mid=a[step].mid();
 47     btree(l,mid,step*2);
 48     btree(mid+1,r,step*2+1);
 49     pushup(step);
 50 }
 51 
 52 void ptree(int l,int r,int val,int step)
 53 {
 54     if(l<=a[step].l&&a[step].r<=r)
 55     {
 56         a[step].col+=val;
 57         a[step].num+=val*(a[step].r-a[step].l+1);
 58         return ;
 59     }
 60     pushdown(a[step].r-a[step].l+1,step);
 61     int mid=a[step].mid();
 62     if(l>mid)
 63         ptree(l,r,val,step*2+1);
 64     else if(r<=mid)
 65         ptree(l,r,val,step*2);
 66     else
 67     {
 68         ptree(l,r,val,step*2);
 69         ptree(l,r,val,step*2+1);
 70     }
 71     pushup(step);
 72 }
 73 
 74 int fintree(int l,int r,int step)
 75 {
 76     if(l<=a[step].l&&a[step].r<=r)
 77          return a[step].num;
 78     pushdown(a[step].r-a[step].l+1,step);
 79     int mid=a[step].mid();
 80     if(l>mid)
 81         return fintree(l,r,step*2+1);
 82     else if(r<=mid)
 83         return fintree(l,r,step*2);
 84     else
 85         return fintree(l,r,step*2)+fintree(l,r,step*2+1);
 86 }
 87 
 88 int main()
 89 {
 90     int n,m,kase,num;
 91     while(scanf("%d %d %d",&n,&m,&kase)!=EOF)
 92     {
 93         for(int i=1;i<=n;i++)
 94             scanf("%d",&b[i]);
 95         btree(1,n,1);
 96         while(kase--)
 97         {
 98             scanf("%d",&num);
 99             int ans=fintree(num,num+m-1,1);
100             printf("%d\n",ans);
101             ptree(num,num+m-1,-1,1);
102         }
103     }
104     return 0;
105 }
View Code

 

转载于:https://www.cnblogs.com/clliff/p/3902265.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值