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

 

你可能感兴趣的:(线段树)