题意:
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; }