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
3 3 1 2 4 1 3 5 1 1 3 4 2 1
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 100009
int 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;
}