SPOJ BGSHOOT 线段树

BGSHOOT - Shoot and kill

The problem is about Mr.BG who is a great hunter. Today he has gone to a dense forest for hunting and killing animals.

Sadly, he has only one bullet in his gun. He wants to kill as many animals as possible with only one bullet.

He has already known the information of duration availability of all animals of the forest.

So, he is planning to shoot at a time so that he could kill maximum animal.

Input

Input begins with an integer N denoting total numbers of animals.

Next N lines contains the duration of availability of animal denoting by X (Starting time) and Y (Ending time) .

Then, there will be Q, denoting the total numbers of queries to be answer.

Each query giving two integer L and RL denoting the time hunter will come to forest and begins shooting

and R denoting last time upto which he will stay at forest for hunting.

Output

For each query output an integer denoting maximum numbers of animals he could kill by shooting at a time during L and R (inclusive).

Constraints:

1<=N,Q<=100000

1<=X,Y,L,R<=1000000000

Example

Input:
4
1 2
2 3
4 5
6 7
4
1 5
2 3
4 7
5 7

Output:
2
2
1
1

题意:有N个动物,第i个动物的活动时间属于[Xi, Yi]。
有Q次询问,每个询问代表你会在[Li, Ri]时间内打猎。
对于每个询问,输出在当前活动时间内动物最多的时刻的动物数。

题解:离散化后扔到线段树里搞一搞  裸的模板题

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
struct node{
    int num,laz;
}tree[1600005];
int l[100005],r[100005],num[400005],x[100005],y[100005];
void build(int t,int l,int r){
    if(l==r){
        tree[t].num=tree[t].laz=0;
        return ;
    }
    int mid=l+r>>1;
    build(t<<1,l,mid);
    build(t<<1|1,mid+1,r);
    tree[t].laz=0;
    tree[t].num=max(tree[t<<1].num,tree[t<<1|1].num);
}
void change(int t,int l,int r,int x,int y){
    if(x<=l&&y>=r){
        tree[t].laz+=1;
        return ;
    }
    int mid=l+r>>1;
    if(x>mid)change(t<<1|1,mid+1,r,x,y);
    else if(y<=mid)change(t<<1,l,mid,x,y);
    else{
        change(t<<1,l,mid,x,y);
        change(t<<1|1,mid+1,r,x,y);
    }
}
void travel(int t,int l,int r,int sum){
    if(l==r){
        sum+=tree[t].laz;
        tree[t].num=sum;
        return ;
    }
    int mid=l+r>>1;
    travel(t<<1,l,mid,sum+tree[t].laz);
    travel(t<<1|1,mid+1,r,sum+tree[t].laz);
    tree[t].num=max(tree[t<<1].num,tree[t<<1|1].num);
}
int ans=0;
void query(int t,int l,int r,int x,int y){
    if(x<=l&&y>=r){
        ans=max(ans,tree[t].num);
        return ;
    }
    int mid=l+r>>1;
    if(y<=mid)query(t<<1,l,mid,x,y);
    else if(x>mid)query(t<<1|1,mid+1,r,x,y);
    else{
        query(t<<1,l,mid,x,y);
        query(t<<1|1,mid+1,r,x,y);
    }
}
int main(){
    int i,j,n,q,cnt=0;
    scanf("%d",&n);
    for(i=1;i<=n;i++){
        scanf("%d%d",&l[i],&r[i]);
        num[++cnt]=l[i];
        num[++cnt]=r[i];
    }
    scanf("%d",&q);
    for(i=1;i<=q;i++){
        scanf("%d%d",&x[i],&y[i]);
        num[++cnt]=x[i];
        num[++cnt]=y[i];
    }
    sort(num+1,num+1+cnt);
    cnt=unique(num+1,num+1+cnt)-num-1;
    build(1,1,cnt);
    for(i=1;i<=n;i++){
        int t1=lower_bound(num+1,num+1+cnt,l[i])-num;
        int t2=lower_bound(num+1,num+1+cnt,r[i])-num;
        change(1,1,cnt,t1,t2);
    }
    travel(1,1,cnt,0);
    for(i=1;i<=q;i++){
        int t1=lower_bound(num+1,num+1+cnt,x[i])-num;
        int t2=lower_bound(num+1,num+1+cnt,y[i])-num;
        ans=0;
        query(1,1,cnt,t1,t2);
        printf("%d\n",ans);
    }
    return 0;
}  
时间: 2024-10-09 20:29:39

SPOJ BGSHOOT 线段树的相关文章

SPOJ GSS3 线段树系列1

SPOJ GSS系列真是有毒啊! 立志刷完,把线段树搞完! 来自lydrainbowcat线段树上的一道例题.(所以解法参考了lyd老师) 题意翻译 n 个数, q 次操作 操作0 x y把 Ax 修改为 y 操作1 l r询问区间 [l,r] 的最大子段和 数据规模在50000,有负数. 冷静分析 因为要维护最大子段和,那么我们可以在线段树struct中维护这么几个信息: sum(区间和).lmax(从左顶点出发的最大子段和).rmax(从右顶点出发的最大子段和).maxx(这段的最大子段和)

spoj GSS线段树以及二维树状数组合集

T1 维护lmax 向左延伸的最大值,rmax同理,sum区间和,ans答案. 转移见operator + #include<bits/stdc++.h> #define mid (l+(r-l)/2) #define ls (rt<<1) #define rs (rt<<1|1) #define int long long using namespace std; const int N =(int)1e5+10; struct TREE { int lef,rig,

spoj 1043 线段树

线段树在解决区间合并问题上还是很强力的,每个结点维护三个值:maxl, maxr, maxn,然后合并操作见pushup函数. 1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 using namespace std; 5 6 const int N = 50001; 7 int a[N]; 8 int sum[N]; 9 10 struct Node 11 { 12 int l, r; 1

spoj 2713 线段树

给定一个序列,有两种操作:对一个区间内的数字开方和求区间内所有数字的和.注意到一个即使很大的数经过没几次开方操作以后就会变成1,而1开方还是1.所以可以用线段树来维护,对于那些全部都是1的区间(即区间和等于区间长度)我们不用更新,剩下的就是区间求和了. 1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 #include <cmath> 5 using namespace std;

spoj GSS2 (线段树) - xgtao -

题目链接 这是一道线段树的题目,维护历史版本,给出N(<=100000)个数字(-100000<=x<=100000),要求求出在[l,r]区间里面的连续序列的最大值,并且重复的数字可以加入序列但是值不能再计算. 数据范围以及区间的查询提示使用线段树,但是我们怎么建树呢?在线操作是没法做的.那就离线吧. 定义s[i] = ai + ai+1 + ai+2 + ... an,以ai开头的数列的和,那么每次加入更新ai 那么s1,s2,...si都会相应的加一个ai,s[1~i]中出现过a[

bzoj 2482: [Spoj GSS2] Can you answer these queries II 线段树

2482: [Spoj1557] Can you answer these queries II Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 145  Solved: 76[Submit][Status][Discuss] Description 给定n个元素的序列. 给出m个询问:求l[i]~r[i]的最大子段和(可选空子段). 这个最大子段和有点特殊:一个数字在一段中出现了两次只算一次. 比如:1,2,3,2,2,2出现了3次,但只算一次,

SPOJ COT3 Combat on a tree(Trie树、线段树的合并)

题目链接:http://www.spoj.com/problems/COT3/ Alice and Bob are playing a game on a tree of n nodes.Each node is either black or white initially. They take turns to do the following operation:Choose a white node v from the current tree;Color all white node

SPOJ 1043 Can you answer these queries I 求任意区间最大连续子段和 线段树

题目链接:点击打开链接 维护区间左起连续的最大和,右起连续的和.. #include <cstdio> #include <iostream> #include <algorithm> #include <string.h> #include <math.h> #include <vector> #include <map> using namespace std; #define N 50050 #define Lson

SPOJ 1557. Can you answer these queries II 线段树

Can you answer these queries II Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 https://www.spoj.com/problems/GSS2/ Description Being a completist and a simplist, kid Yang Zhe cannot solve but get Wrong Answer from most of the OI problems. And he refuse