ZOJ3453 Doraemon's Sweet Bullet(线段树单点更新+区间更新+区间查询)
来源:互联网 发布:c语言文件加密程序 编辑:程序博客网 时间:2024/06/06 16:56
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;}
- ZOJ3453 Doraemon's Sweet Bullet(线段树单点更新+区间更新+区间查询)
- ZOJ 3453 Doraemon's Sweet Bullet(线段树区间更新+单点更新+最值询问)
- zoj (单点更新区间查询:线段树)
- 线段树单点更新和区间查询
- hdu1166(线段树单点更新区间查询)
- hdu5316 Magician (线段树+单点更新+区间查询+区间合并)
- ZOJ-3453---Doraemon's Sweet Bullet (线段树)
- [模板]线段树的建树、查询、单点更新、区间更新
- 线段树(单点更新+区间更新)
- FZU Problem 2240 Daxia & Suneast's problem(博弈+[单点更新,区间查询]线段树)
- 线段树(堆式)[单点更新, 区间查询]
- hdoj 4339 线段树 单点更新,区间查询
- HDU 2795 线段树(单点更新 区间查询)
- HDOJ3016Man Down(线段树(区间更新,单点查询)+DP)
- HDU1754线段树单点更新区间查询(数组版)
- Necklace (线段树单点更新+区间查询+离线操作)
- HDU 4819:单点更新,区间查询的二维线段树
- hdu 4046 Panda (线段树 单点更新 区间查询)
- Eclipse 导入web项目后 报 The type javax.servlet.http.HttpServletRequest cannot be resolved.
- OC学习----可变字符串
- 【leetcode】Palindrome Linked List
- Http协议中的各种长度限制总结
- php图形图像处理基础
- ZOJ3453 Doraemon's Sweet Bullet(线段树单点更新+区间更新+区间查询)
- 区别script中的type=”text/javascript”和language=”Javascript”
- android之WakeLock机制浅析
- MVVM指南一:Flickr搜索实例
- ajax 验证用户名是否存在
- 用U盘启动盘重装系统启动时黑屏
- html及css学习笔记_2_html基本结构
- 数据结构---位运算
- HDU 5317(2015多校3)-RGCDQ(数论)