题意:
塔防游戏,一条n长的路上,有m个炮台,可以覆盖[li,ri]范围,威力ci,即每一秒,炮塔可以对范围 内的怪物可以造成ci点伤害。只有有q只怪物,每只怪物有hi点血,出现位置为xi;当怪物血量减少到0或以下时消失,怪物一直朝n位置前进。问有几只怪物可以离开这条路。
题解:
一开始看到这个题目就想到了线段树,最简单那种线段求和。不过作者好坑人啊,卡大数据。。TLE,之后没去想O(n)算法,直接快速读入险过。
其实这个有更加简便的方法(习惯性想到线段树害死人啊。)详细的看代码,不好说明,就是用e数组记录边界就可以了。
代码:
1.O(n)算法
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <queue>
#include <map>
#include <set>
#include <vector>
#include <cctype>
using namespace std;
#define LL __int64
const int maxn=1e5+10;
int e[maxn];
LL sum[maxn];
inline int readint()
{
int x=0;
char ch;
ch=getchar();
while(!isdigit(ch))ch=getchar();
while(isdigit(ch))
{
x=x*10+ch-'0';
ch=getchar();
}
return x;
}
inline LL readint2()
{
LL x=0;
char ch;
ch=getchar();
while(!isdigit(ch))ch=getchar();
while(isdigit(ch))
{
x=x*10+ch-'0';
ch=getchar();
}
return x;
}
int main()
{
int n;
while(n=readint())
{
memset(e,0,sizeof(e));
int i,j,k,m,a,b,c;
//scanf("%d",&m);
m=readint();
for(i=0;i<m;i++)
{
//scanf("%d%d%d",&a,&b,&c);
a=readint();
b=readint();
c=readint();
e[a-1]-=c;
e[b]+=c;
}
sum[n+1]=0;
LL x=0;
for(i=n;i>=1;i--)
{
x+=e[i];
sum[i]=sum[i+1]+x;
}
//for(i=1;i<=n;i++)printf("%I64d\n",sum[i]);
int q,y,ans=0;
//scanf("%d",&q);
q=readint();
while(q--)
{
//scanf("%I64d%d",&x,&y);
x=readint2();
y=readint();
if(x>sum[y])ans++;
}
printf("%d\n",ans);
}
return 0;
}
2.线段树
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <queue>
#include <map>
#include <set>
#include <vector>
#include <cctype>
using namespace std;
#define LL __int64
const int maxn=1e5+10;
struct node{
int l,r;
LL w,addv;
}e[maxn*4];
void build(int a,int b,int c)
{
e[c].l=a;e[c].r=b;e[c].w=e[c].addv=0;
if(a==b)return ;
int mid=(a+b)>>1;
build(a,mid,c<<1);
build(mid+1,b,(c<<1)|1);
}
void push_down(int c)
{
if(e[c].addv)
{
e[c<<1].addv+=e[c].addv;e[(c<<1)|1].addv+=e[c].addv;
e[c<<1].w+=e[c].addv*(e[c<<1].r-e[c<<1].l+1);
e[(c<<1)|1].w+=e[c].addv*(e[(c<<1)|1].r-e[(c<<1)|1].l+1);
e[c].addv=0;
}
}
void update(int a,int b,int c,int val)
{
if(e[c].l==a&&e[c].r==b)
{
e[c].w+=(LL)val*(e[c].r-e[c].l+1);
e[c].addv+=val;
return ;
}
push_down(c);
int mid=(e[c].l+e[c].r)>>1;
if(b<=mid)update(a,b,c<<1,val);
else if(a>mid)update(a,b,(c<<1)|1,val);
else
{
update(a,mid,c<<1,val);
update(mid+1,b,(c<<1)|1,val);
}
e[c].w=e[c<<1].w+e[(c<<1)|1].w;
}
LL query(int a,int b,int c)
{
if(e[c].l==a&&e[c].r==b)
{
return e[c].w;
}
push_down(c);
int mid=(e[c].l+e[c].r)>>1;
if(b<=mid)return query(a,b,c<<1);
else if(a>mid)return query(a,b,(c<<1)|1);
else return query(a,mid,c<<1)+query(mid+1,b,(c<<1)|1);
}
int readint()
{
int x=0;
char ch;
ch=getchar();
while(!isdigit(ch))ch=getchar();
while(isdigit(ch))
{
x=x*10+ch-'0';
ch=getchar();
}
return x;
}
LL readint2()
{
LL x=0;
char ch;
ch=getchar();
while(!isdigit(ch))ch=getchar();
while(isdigit(ch))
{
x=x*10+ch-'0';
ch=getchar();
}
return x;
}
int main()
{
//freopen("D:\\in.txt","r",stdin);
int n;
while(scanf("%d",&n)!=EOF)
{
if(n==0)break;
int i,j,k,m,a,b,c,f,q,ans=0;
LL x,d;
build(1,n,1);
scanf("%d",&m);
for(i=0;i<m;i++)
{
//scanf("%d%d%d",&a,&b,&c);
a=readint();
b=readint();
c=readint();
update(a,b,1,c);
}
scanf("%d",&q);
while(q--)
{
//scanf("%I64d%d",&d,&f);
d=readint2();
f=readint();
x=query(f,n,1);
//cout<<x<<endl;
if(x<d)ans++;
}
//for(i=1;i<=n;i++)printf("*%I64d\n",query(i,n,1));
printf("%d\n",ans);
}
return 0;
}
/*
10
5
1 7 1
3 4 2
2 9 4
7 10 8
7 7 2
4
8 10
7 10
9 10
77 1
*/