ZOJ3453 Doraemon's Sweet Bullet(线段树单点更新+区间更新+区间查询)

来源:互联网 发布:c语言文件加密程序 编辑:程序博客网 时间:2024/06/06 16:56
Doraemon's Sweet Bullet

Time Limit: 2 Seconds      Memory Limit: 65536 KB

Doraemon likes to shoot his enemies with sweet bullets.

n "enemies" stand in a line, each with a life value li (the index i increases from left to right side and starts from 1). Each time Doraemon shoots a sweet bullet from the right side. The ith bullet has a "critical range" ki. That is to say, it attacks the first enemy from right side whose life value is equal to or greater than ki. The life value of the attacked enemy will decrease to 1 immediately.

However, Doraemon finds a terrible fact that after an enemy is attacked, it will distribute the sweets to his friends and his friends' life value will increase by 1. For the ith enemy, his friends are in a consecutive range from the aith enemy to the bith. Note that an enemy may be the friend of himself so that after being attacked his life value will be 2.

What's more, if a bullet can't find a target--there doesn't exist an enemy with life greater or equal than ki, all enemies' life will increase by 1.

Now Doraemon wants to know after m bullets were shot, what the maximum life value in all enemies is.

Input

The input contains multiple test cases.

Each test case begins with a line containing a single integer n (1 ≤ n ≤ 100000) indicating the number of enemies.

The following n lines describes enemies, one enemy each line. Each line contains three integers, the initial life value li (1 ≤ li ≤ 10000) and his range of friends ai bi (1 ≤ ai ≤ bi≤ n) - that is, enemies with index from ai to bi (inclusive) are all his friends.

The following line contains an integer m (1 ≤ m ≤ 100000) indicating the number of bullets Doraemon has shot. The last m lines follows, each with a single integer ki (1 ≤ ki ≤ 10000) describing the bullet's "critical range".

Different cases are separated by a blank line.

Process to the end of input.

Output

For each test case, output the maximum life value after shooting in a single line.

Sample Input

33 1 24 1 35 1 13421

Sample Output

6

题意:有N个敌人,排成一排编号为1~n;对于敌人i有一个初始value[i];对于敌人i,其朋友范围区间[Li,Ri],i可能在[Li,Ri]区间内。你每次从右边发射子弹,第i颗子弹值为Ki,打中第一个value值大于或等于Ki的敌人,该敌人value值变为1,其朋友范围内的敌人value值均增加1;但是,如果没有敌人的value值大于或者等于Ki,则所有敌人value值增加1。求最后敌人中最高的value值。

解法:线段树,每个节点设置一个max、add元素,max表示该区间上的最大值,add表示该区间增加的值;实现(1)区间段元素+1操作,即对应的区间add+1;(2)对于对某个value值置1,即可将该点覆盖的所有区间add累加值+1;(3)查找大于或等于K的最右元素。

#include <iostream>#include <cstdio>#include <cstring>#include <iomanip>#include <cmath>#include <algorithm>#include <cstdlib>using namespace std;#define maxn 100009int val[maxn],l[maxn],r[maxn]; //val存原来的值 l、r保存区间端点int n;struct Tree{    int s,t;    int max_val;    int add; //其实相当于lazy标记}tree[maxn*4]; //树的大小要开到原来的4倍void build(int id,int s,int t){    tree[id].s=s;    tree[id].t=t;    tree[id].add=0;    if(s==t)    {        tree[id].max_val=val[s];        return;    }    int mid=(tree[id].s+tree[id].t)>>1;    build(id*2,s,mid);    build(id*2+1,mid+1,t);    tree[id].max_val=max(tree[id*2].max_val,tree[id*2+1].max_val);//存大的}void pushdown(int id)//延迟更新{    if(tree[id].add!=0)    {        tree[id*2].max_val+=tree[id].add;        tree[id*2+1].max_val+=tree[id].add;        tree[id*2].add+=tree[id].add;        tree[id*2+1].add+=tree[id].add;        tree[id].add=0;    }}void update1(int id,int s) //单点更新(被子弹打到的点){    if(tree[id].s==s && tree[id].t==s)    {        tree[id].max_val=1;        return;    }    int mid=(tree[id].s+tree[id].t)>>1;    if(mid<s)        update1(id*2+1,s);    else        update1(id*2,s);    tree[id].max_val=max(tree[id*2].max_val,tree[id*2+1].max_val);}void update2(int id,int s,int t,int val)//这里val的值其实是1{    if(tree[id].s==s && tree[id].t==t)    {        tree[id].add+=val;        tree[id].max_val+=val;        return;    }    int mid=(tree[id].s+tree[id].t)>>1;    pushdown(id); //延迟更新操作    if(s>mid)        update2(id*2+1,s,t,val);    else if(t<=mid)        update2(id*2,s,t,val);    else    {        update2(id*2,s,mid,val);        update2(id*2+1,mid+1,t,val);    }    tree[id].max_val=max(tree[id*2].max_val,tree[id*2+1].max_val);}int query(int id,int s,int t,int aim) //从右边开始查找第一个大于等于aim的{    if(s==t)        return s;    int mid=(tree[id].s+tree[id].t)>>1;    pushdown(id);    if(tree[id*2+1].max_val>=aim)        return query(id*2+1,mid+1,t,aim);    else        return query(id*2,s,mid,aim);}int main(){    while(~scanf("%d",&n))    {        for(int i=1;i<=n;i++)        {            scanf("%d %d %d",&val[i],&l[i],&r[i]);        }        build(1,1,n);        int m,tmp;        scanf("%d",&m);        for(int i=1;i<=m;i++)        {            scanf("%d",&tmp);            if(tmp>tree[1].max_val)                update2(1,1,n,1);            else            {                int p=query(1,1,n,tmp);                update1(1,p);                update2(1,l[p],r[p],1);            }        }        printf("%d\n",tree[1].max_val);    }    return 0;}


0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 想打嗝打不出来怎么办 孩子满100天要怎么办 宝宝吃奶粉过敏了怎么办 1岁宝宝不喝奶粉怎么办 母乳不够宝宝不喝奶粉怎么办 宝宝吃奶粉上火了怎么办 我小孩不喝奶粉怎么办 2岁宝宝不喝奶粉怎么办 婴儿吃奶粉上火了怎么办 100天的宝宝咳嗽怎么办 40天的小孩咳嗽怎么办 40天的婴儿咳嗽怎么办 50天的婴儿咳嗽怎么办 宝宝20天感冒了怎么办 1个月宝宝咳嗽怎么办 40天的宝宝干咳怎么办 百天的宝宝咳嗽怎么办 50天的孩子咳嗽怎么办 百天宝宝咳嗽有痰怎么办 1岁半宝宝拉肚子怎么办 百天的宝宝拉肚子怎么办 激战2帧数三十多怎么办 太受欢迎了怎么办txt微 太受欢迎了怎么办网盘 太受欢迎了怎么办微盘 我太受欢迎了该怎么办h 我太受欢迎了该怎么办1 卡培他滨副作用怎么办 究极风暴4卡怎么办 脸下垂法令纹深怎么办 20岁有法令纹怎么办 3个月婴儿铅超标怎么办 一岁宝宝铅超标怎么办 小樱死了 佐助怎么办 平板玩游戏闪退怎么办 手机玩游戏闪退怎么办 天天爱消除闪退怎么办 半夜牙疼的厉害怎么办 心眼特别小的人怎么办 自己心眼太小了怎么办 我心眼小爱生气怎么办