题目大意:
怪物在一条直线上运动,怪物i都是从xi(坐标)移到到n去,怪物每秒前进一格。在直线上有m个防御塔,每个防御塔有个攻击范围L-R,每秒防御塔能攻击所有处于L-R之间的怪物。
给你K个怪物,怪物i的血量为Hi,初始坐标为Xi
求最后存活了多少个怪物
方法一:
用段树区间维护求出每个点所受的伤害再统计最后存活的怪物即可,但是会TLE, 不过用了输入外挂后能AC 0.5S(以前某渣知道这个东西的好处)
方法二:
直接用一个一维数组去维护区间伤害值的更新,对于了l,r,d 则a[l]+= d,a[r-1]+=d , 第i个位置的伤害就是数组a的1-i的前缀和
然后再从后往前累计一次就可以得到第i个位置会受到的最大伤害值
PS: 感觉这个维护区间伤害的方法有点吊。。。 我想都没想都写线段树了。。
线段树代码:
//线段树
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define LL __int64
#define maxn 100005
struct nofr
{
int l, r;
LL add;
}a[4*maxn];
LL s[maxn];
void Build(int l, int r, int n)
{
a[n].l= l;
a[n].r= r;
a[n].add= 0;
if(a[n].l== a[n].r)
return;
int mid= (a[n].l + a[n].r)/2;
Build(l, mid, 2*n);
Build(mid+1, r, 2*n+1);
}
void pushdown(int n)
{
if(a[n].add)
{
if(a[n].l== a[n].r)
return;
a[2*n].add+= a[n].add;
a[2*n+1].add+= a[n].add;
a[n].add= 0;
}
}
void add(int l, int r, int n, int d)
{
pushdown(n);
// printf("%d %d %d ",a[n].l,a[n].r,n);
if(a[n].l== l && a[n].r== r)
{
a[n].add+= d;
return;
}
int mid= (a[n].l + a[n].r)/ 2;
// printf("%d %d %d\n",l,r,mid);
if(r<= mid)
add(l, r, 2*n, d);
else if(l> mid)
add(l, r, 2*n+1, d);
else
{
add(l, mid, 2*n, d);
add(mid+1, r, 2*n+1, d);
}
}
void Query(int n, LL sum)
{
//printf("%d\n",n);
sum+= a[n].add;
if(a[n].l== a[n].r)
{
s[a[n].l]= sum;
return;
}
Query(2*n, sum);
Query(2*n+1, sum);
}
int get_val()
{
int ret=0;
char c;
while((c=getchar())!=' '&&c!='\n')
ret=ret*10+c-'0';
return ret;
}
LL g_val()
{
LL ret=0;
char c;
while((c=getchar())!=' '&&c!='\n')
ret=ret*10+c-'0';
return ret;
}
int main()
{
int n;
while(scanf("%d",&n)!=EOF&& n)
{
getchar();
Build(1, n, 1);
int m;
//scanf("%d",&m);
m= get_val();
while(m--)
{
int l, r, d;
//scanf("%d %d %d",&l,&r,&d);
l= get_val();
r= get_val();
d= get_val();
add(l, r, 1, d);
}
memset(s, 0, sizeof(s));
Query(1, 0);
for(int i= n; i>= 1; i--)
s[i]+= s[i+1];
int k;
int ans= 0;
//scanf("%d",&k);
k= get_val();
while(k--)
{
LL hi;
int xi;
//scanf("%I64d",&hi);
hi= g_val();
//scanf("%d",&xi);
xi= get_val();
if(s[xi]< hi)
ans++;
}
printf("%d\n",ans);
}
return 0;
}
代码二:
#include <cstdio>
#include <cstring>
#define maxn 100005
#define LL __int64
LL s[maxn];
int main()
{
int n;
while(scanf("%d",&n)!=EOF&&n)
{
memset(s, 0, sizeof(s));
int m;
scanf("%d",&m);
while(m--)
{
int l, r, d;
scanf("%d %d %d",&l,&r,&d);
s[l]+= d;
s[r+1]-= d;
}
for(int i= 1; i<= n; i++)
s[i]+= s[i-1];
for(int i= n-1; i>= 1; i--)
s[i]+= s[i+1];
int k;
int ans= 0;
scanf("%d",&k);
while(k--)
{
LL hi;
int xi;
scanf("%I64d %d",&hi,&xi);
if(s[xi]< hi)
ans++;
}
printf("%d\n",ans);
}
return 0;
}