现在的位置: 首页 > 综合 > 正文

HDOJ 4031 – Attack 区间更新点查询的树状数组+暴力…

2013年10月17日 ⁄ 综合 ⁄ 共 1424字 ⁄ 字号 评论关闭

               题意:

                       911十周年之际..恐怖份子准备再次发动攻击...现在设立了N个防御塔..每个防御塔抵挡了一次攻击后..要技能能却T时间后才能再次防御..而当一个防御塔处于冷却状态时,收到的攻击就会都接受...而恐怖份子的武器很厉害..每次会攻击一个连续的范围...现在告诉恐怖份子发动攻击的情况...并且中间询问某个防御塔成功受到了多少次攻击.

               题解:

                       把受到攻击的次数与成功防御的次数分开算...受到攻击的数目so easy了..区间更新点查询..一般使用线段树..这里学者用树状数组整..区间求和..比如要更新(l,r)每个数加1可以update(1,l),update(-1,r+1)..完成区间更新..而要查看某个位置x的值就直接看sum[x]...

                       统计成功防御次数..很暴力..记录一边做一边记录该点上一次成功防御的时刻...并且当询问该点时才更新...时间复杂度大致为O(M*N/T) 最坏情况

Program:

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<queue>
#include<stack>
#include<algorithm>
#include<cmath>
#include<set>
#include<map>
#include<time.h>
#define ll long long
#define oo 1<<29
#define MAXN 50005
#define pi acos(-1.0)
#define esp 1e-30
using namespace std;   
int sum[MAXN],N;  
void update(int x,int k)
{
       while (k<=N)
       {
              sum[k]+=x;
              k+=k&(-k);
       }
}
int query(int k)
{
       int ans=0;
       while (k)
       {
              ans+=sum[k];
              k-=k&(-k);
       }
       return ans;
}
char s[10];
int pre[MAXN],attack[MAXN][2],d[MAXN];
int main()
{    
       int C,cases,M,T,i,x,l,r,An;  
       scanf("%d",&C);
       for (cases=1;cases<=C;cases++)
       {
                scanf("%d%d%d",&N,&M,&T);
                printf("Case %d:\n",cases);
                memset(sum,0,sizeof(int)*(N+1));
                memset(d,0,sizeof(int)*(N+1));
                for (i=1;i<=N;i++) pre[i]=1;
                An=0;
                while (M--)
                {
                         scanf("%s",s);
                         if (s[0]=='A') 
                         {
                                 scanf("%d%d",&l,&r);
                                 update(1,l),update(-1,r+1);
                                 attack[++An][0]=l,attack[An][1]=r;
                         }else
                         {
                                 scanf("%d",&x);
                                 if (!T) { puts(0); continue; }
                                 for (i=pre[x];i<=An;i++) //暴力更新防御次数
                                    if (attack[i][0]<=x && attack[i][1]>=x)
                                       d[x]++,pre[x]=i+T,i+=T-1; 
                                 printf("%d\n",query(x)-d[x]);
                         }
                }                
       }
       return 0;
}

抱歉!评论已关闭.