您的位置:首页 > 其它

哈理工OJ 2256 南西群岛海域·冲之岛近海(线段树区间更新+前缀和优化)

2017-01-12 23:09 369 查看
题目链接:http://acm.hrbust.edu.cn/index.php?m=ProblemSet&a=showProblem&problem_id=2256

南西群岛海域·冲之岛近海

Time Limit: 3000 MS Memory Limit: 32768 K

Total Submit: 150(58 users) Total Accepted: 56(51 users) Rating: Special Judge: No

Description

报告称本海域有敌人反攻的前兆。编成以巡洋舰为中心的警戒部队,探明敌舰队动向。

假定当前敌舰采用了排成一行的阵型,m只敌舰分别在从1到m的位置上。(包括1和m。)在一场战斗的炮击阶段,每个舰娘都可以对一个范围内的所有敌舰造成一定的伤害。如果敌舰受到的伤害大于了自己的血量,就会被击沉。可是愚蠢、调皮又二次元的提督小林,他想知道任意一个区间有多少只敌舰被击沉了。你能帮助他么?

Input

输入由有多组数据组成,每组数据的第一行包括了三个整数m、n和q,分别表示敌舰的个数、舰娘的个数和小林的询问的个数。(1≤m,n≤10^5,q≤1000)

接下来的一行包括m个整数,表示每个敌舰的血量a。(1≤a≤10^9)

接下来的n行,每行包括了三个整数,L、R、x,表示对[L,R]范围内的所有敌舰造成x点伤害。(1≤L,R≤m, 1≤x≤100)

接下来的q行,每行包括了两个整数,L和R。你需要输出[L,R]范围内被击沉的敌舰的个数。

Output

对于每个查询输出包括一行,有一个整数,表示被击沉的敌舰的个数。

Sample Input

2 1 1

1 1

1 2 2

1 2

3 1 1

1 2 3

1 3 2

1 3

Sample Output

2

1

Source

“尚学堂杯”2015级程序设计竞赛(10月)正式赛

Author

TwIStOy

【思路分析】直接区间更新,然后前缀和搞一下就OK了,可能解题方法有点挫…。

【AC代码】

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
#define ll long long

struct node
{
ll left,right,val,lazy,len;
} c[100005];

void build_tree(ll l,ll r,ll root)
{
c[root].left=l;
c[root].right=r;
c[root].lazy=0;
c[root].len=(c[root].right-c[root].left+1);
if(c[root].left==c[root].right)
{
scanf("%lld",&c[root].val);
return ;
}
ll mid=(c[root].left+c[root].right)/2;
build_tree(l,mid,root*2);
build_tree(mid+1,r,root*2+1);
c[root].val=c[root*2].val+c[root*2+1].val;
}

void pushdown(ll root)
{
if(c[root].lazy!=0)
{
c[root*2].lazy+=c[root].lazy;
c[root*2+1].lazy+=c[root].lazy;

c[root*2].val += c[root].lazy * (c[root*2].right - c[root*2].left + 1);
c[root*2 + 1].val += c[root].lazy * (c[root*2 + 1].right - c[root*2 + 1].left + 1);
c[root].lazy=0;
}
}

ll search_tree(ll l,ll r,ll root)
{
if(c[root].left==l&&c[root].right==r)
{
return c[root].val;
}
if(c[root].lazy!=0)
{
pushdown(root);
}
ll sum;
ll mid=(c[root].left+c[root].right)/2;
if(mid<l)
{
sum=search_tree(l,r,root*2+1);
}
else  if(r<=mid)
{
sum=search_tree(l,r,root*2);
}
else
{
sum=search_tree(l,mid,root*2)+search_tree(mid+1,r,root*2+1);
}
return sum;
}

void update_tree(ll l,ll r,ll root,ll x)
{
if(c[root].left==l&&c[root].right==r)
{
c[root].lazy+=x;
c[root].val += x * (r - l + 1);
return;
}
pushdown(root);
ll mid=(c[root].left+c[root].right)/2;
if(mid<l)
{
update_tree(l,r,root*2+1,x);
}
else if(mid>=r)
{
update_tree(l,r,root*2,x);
}
else
{
update_tree(l,mid,root*2,x);
update_tree(mid+1,r,root*2+1,x);
}
c[root].val=c[root*2].val+c[root*2+1].val;
}

ll sum[100005];
int main()
{
ll n,m,q;
while(~scanf("%lld%lld%lld",&m,&n,&q))
{
memset(c,0,sizeof(c));
build_tree(1,m,1);
ll a,b,x;
for(int i=0; i<n; i++)
{
scanf("%lld%lld%lld",&a,&b,&x);
update_tree(a,b,1,-x);
}
sum[0]=0;
for(int i=1;i<=m;i++)
{
if(search_tree(i,i,1)<0)
{
//printf("%lld**\n",search_tree(i,i,1));
sum[i]=sum[i-1]+1;
}
else
{
sum[i]=sum[i-1];
}
}
sum[m+1]=sum[m];
ll l,r;
for(int i=1;i<=q;i++)
{
scanf("%lld%lld",&l,&r);
printf("%lld\n",(sum[r]-sum[l-1]));
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  哈理工OJ