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

来源:互联网 发布:缸中之脑 知乎 编辑:程序博客网 时间:2024/04/29 13:57

题目链接: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 longstruct 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;}
0 0
原创粉丝点击