ZOJ-3453---Doraemon's Sweet Bullet (线段树)

来源:互联网 发布:linux重命名命令 编辑:程序博客网 时间:2024/06/08 02:45
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 indexi increases from left to right side and starts from 1). Each time Doraemon shoots a sweet bullet from the right side. Theith 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 thanki.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 theith enemy, his friends are in a consecutive range from the aith enemy to thebith. 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 thanki, 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 valueli (1 ≤ li ≤ 10000) and his range of friendsai bi (1 ≤ aibi≤ n) - that is, enemies with index fromai 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 lastm 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

Hint

Doraemon suggests that you should use scanf to read data.


题意:N个敌人排成一行,每个人都有一个生命值和朋友范围我方射出一颗值为K的子弹,这个子弹只能打中敌人生命值大于等于K的敌人。子弹从右往左,子弹只能打中一人,打中敌人以后,敌人的生命值降为1,他朋友范围内的人生命值加1;如果敌人范围内没有>=K的值,就是说子弹打不中敌人,那么所有人的生命值+1;

思路:很明显的线段树,用到区间更新,单点更新;具体看代码
AC代码:
#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;int n,q;struct ee{    int val;int l;int r;int id;//id为编号}ren[100010];struct node{    int l,r;    int val;//当前区间最大的血量    int lf,rf;//朋友区间    int id;//记录血量最大的人的编号    int tag;//增加的生命值}segtree[100010*4];void pushup(int root){    segtree[root].val=max(segtree[root<<1].val,segtree[root<<1|1].val);    segtree[root].id=segtree[root<<1].val>segtree[root<<1|1].val?segtree[root<<1].id:segtree[root<<1|1].id;}void build(int root,int l,int r){    segtree[root].l=l;    segtree[root].r=r;    segtree[root].tag=0;    if(l==r)    {        segtree[root].val=ren[l].val;        segtree[root].lf=ren[l].l;        segtree[root].rf=ren[l].r;        segtree[root].id=ren[l].id;        return ;    }    int mid=(l+r)>>1;    build(root<<1,l,mid);    build(root<<1|1,mid+1,r);    pushup(root);}void pushdown(int root){    if(segtree[root].tag)    {        segtree[root<<1].val+=segtree[root].tag;        segtree[root<<1|1].val+=segtree[root].tag;        segtree[root<<1].tag+=segtree[root].tag;        segtree[root<<1|1].tag+=segtree[root].tag;        segtree[root].tag=0;    }}void update(int root,int l,int r){    int ll=segtree[root].l;    int rr=segtree[root].r;    if(l<=ll&&rr<=r)    {        segtree[root].val++;        segtree[root].tag++;        return;    }    pushdown(root);    int mid=(ll+rr)>>1;    if(l<=mid)update(root<<1,l,r);    if(r>mid) update(root<<1|1,l,r);    pushup(root);}void _update(int root,int p){    int ll=segtree[root].l;    int rr=segtree[root].r;    if(ll==rr)    {        segtree[root].val=1;        segtree[root].tag=0;        return;    }    pushdown(root);    int mid=(ll+rr)>>1;    if(p<=mid) _update(root<<1,p);    else  _update(root<<1|1,p);    pushup(root);}int _find(int root,int x){    if(segtree[root].l==segtree[root].r)        return segtree[root].id;    pushdown(root);    if(segtree[root<<1|1].val>=x)//优先考虑右边        return _find(root<<1|1,x);    else        return _find(root<<1,x);    pushup(root);}int main(){    while(~scanf("%d",&n))    {        for(int i=1;i<=n;i++)        {            scanf("%d%d%d",&ren[i].val,&ren[i].l,&ren[i].r);            ren[i].id=i;        }        build(1,1,n);        int x;        scanf("%d",&q);        while(q--)        {            scanf("%d",&x);            if(x>segtree[1].val)//最大血量小于x,所有人血量加一                update(1,1,n);            else            {                int id=_find(1,x);//找到第一个血量比x大的人的id                _update(1,id);//将这个人血量置为1                update(1,ren[id].l,ren[id].r);//朋友学俩个都加1            }        }        printf("%d\n",segtree[1].val);    }    return 0;}


原创粉丝点击