hdu 4031 attack 树状数组 线段树 两种做法
被攻击的次数等于总的攻击次数减去成功防守的次数
这道题目其实主要考如何计算成功防守的次数
增加一个辅助数组pos【】,记录上次询问后某个点防守到了第几次进攻(第一次进攻都能防守住)
每防守住一次,就过t0-1次进攻,继续判断接下来的第t0次进攻有没有包括(即攻击到)询问的点
有的人说复杂度是O(n^2),最坏复杂度确实可能是O(q)*O(q/t)log(n),应该是超时边缘,但就是过了,开个挂后速度还不错。。。可能数据不强
View Code
#include<cstdio>
#include<cstring>
const int maxn = 20001;
int c[maxn];
struct pp{
int l,r;
}att[maxn];
inline int lowbit(int x){
return x&-x;
}
inline void update(int x,int d){
for(;x<maxn;x+=lowbit(x))
c[x]+=d;
}
int sum(int x){
int ans=0;
for(;x>0;x-=lowbit(x))
ans+=c[x];
return ans;
}
int defen[maxn],pos[maxn];
int main(){
int t,cases=1,i,j,t0,a,b,n,q;
char s[10];
scanf("%d",&t);
while(t--){
int tot=0;
memset(c,0,sizeof(c));
memset(pos,0,sizeof(pos));
memset(defen,0,sizeof(defen));
scanf("%d%d%d",&n,&q,&t0);att[0].l=att[0].r=0;
printf("Case %d:\n",cases++);
while(q--){
scanf("%s",s);
if(s[0]=='A'){
scanf("%d%d",&a,&b);
tot++;
att[tot].l=a;att[tot].r=b;
update(a,1);
update(b+1,-1);
}
else {
scanf("%d",&a);
for(i=pos[a];i<=tot;i++){
if(a>=att[i].l&&a<=att[i].r){
pos[a]=i+t0;
defen[a]++;
i+=t0-1;
}
}
printf("%d\n",sum(a)-defen[a]);
}
}
}
return 0;
}
线段树+注释
View Code
#include<cstdio>
#include<cstring>
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
const int maxn = 20001;
int sum[maxn<<2];
int col[maxn<<2];
struct pp{
int l,r;
}att[maxn];
int defen[maxn],pos[maxn];
void update(int L,int R,int l,int r,int rt){
if(L<=l&&r<=R){//完全覆盖就不再更新了,否则就退化成O(n),必然导致超时
sum[rt]++;
return ;
}
int m=(l+r)>>1;
if(L<=m) update(L,R,lson);
if(R>m) update(L,R,rson);
}
int query(int p,int l,int r,int rt){//依次把树上的覆盖次数相加,加到底的时候就是某个点的覆盖次数了
if(l==r){
return sum[rt];
}
int m=(l+r)>>1;
int ret=0;
ret+=sum[rt];
if(p<=m) return ret+query(p,lson);
else return ret+query(p,rson);
}
int main(){
int t,cases=1,i,j,t0,a,b,n,q;
char s[10];
scanf("%d",&t);
while(t--){
int tot=0;
memset(pos,0,sizeof(pos));
memset(defen,0,sizeof(defen));
scanf("%d%d%d",&n,&q,&t0);att[0].l=att[0].r=0;
memset(rt,0,sizeof(rt));
printf("Case %d:\n",cases++);
while(q--){
scanf("%s",s);
if(s[0]=='A'){
scanf("%d%d",&a,&b);
tot++;
att[tot].l=a;att[tot].r=b;
update(a,b,1,n,1);
}
else {
scanf("%d",&a);
for(i=pos[a];i<=tot;i++){
if(a>=att[i].l&&a<=att[i].r){
pos[a]=i+t0;
defen[a]++;
i+=t0-1;
}
}
printf("%d\n",query(a,1,n,1)-defen[a]);
}
}
}
return 0;
}