线段树水题区间最大值,最小值,求和CDOJ1921

饺子发现身边危机四伏!有nn个人站在一维平面上,每个人的坐标为Ai,能量值为Bi。饺子有cc种方法可以推测出有多少人想吃饺子,请你求出每种方法可以得出的想吃饺子的人数。

Input

第一行两个值 n(n≤105),c(c≤10)n
接下来n行每行两个值Ai,Bi(1≤Ai≤109,1≤Bi≤104,Ai≤Aj)  if Q__Q题目链接 接下来c行,每行包含三个数K,function
其中 
K可能为gt或者lt,代表大于或者小于 
function可能为minmax或者avg,代表最小,最大或者平均 
length是一个整数(1≤length≤109)
K,function,length的意思为对于第ii号人,如果Bi K于[Ai−length,Ai)范围内的所有人能量值的function值,说明该人想吃饺子,特别的如果范围内一个人也没有,则这个人不想吃饺子

Output

对于每种方法,输出想吃饺子的人数

Sample Input

10 2
60 30
120 28
180 35
240 34
300 40
360 31
420 28
480 2
540 42
600 30
gt avg 7200
lt min 300

Sample Output

4
2

需要将区间[Ai−length,Ai) 处理到线段树的1--n区间上,由于A是升序排列的,所以二分查找到区间左端的下标

#include
#include
#include
#include
using namespace std;
const int INF=0x3f3f3f3f;
const int maxn=1e5+7;
long long btree[400005];
int bmax[400005];
int bmin[400005];
int n,c;
int a[maxn];
int b[maxn];
void buildtree(int l,int r,int rt)//建树,rt为当前位置
{
    if(l==r)
    {
        btree[rt]=b[l];
        bmin[rt]=b[l];
        bmax[rt]=b[l];
        return ;
    }
    int mid=(l+r)>>1;;
    buildtree(l,mid,rt*2);
    buildtree(mid+1,r,rt*2+1);
    btree[rt]=btree[rt*2]+btree[rt*2+1];
    bmax[rt]=max(bmax[rt<<1],bmax[rt<<1|1]);
    bmin[rt]=min(bmin[rt<<1],bmin[rt<<1|1]);
}
long long findsum(int l,int r,int rt,int ll,int rr)//查询区间的和,ll区间左端,rr区间右端
{
    if(ll<=l&&r<=rr) return btree[rt];
    int mid=l+(r-l)/2;
    long long ans=0;
    if(ll<=mid) ans+=findsum(l,mid,rt*2,ll,rr);
    if(rr>mid) ans+=findsum(mid+1,r,rt*2+1,ll,rr);
    return ans;
}
int findmax(int l,int r,int rt,int ll,int rr)
{
    if(ll<=l&&r<=rr) return bmax[rt];
    int mid=l+(r-l)/2;
    int ans=-INF;
    if(ll<=mid) ans=max(ans,findmax(l,mid,rt*2,ll,rr));
    if(rr>mid) ans=max(ans,findmax(mid+1,r,rt*2+1,ll,rr));
    return ans;
}
int findmin(int l,int r,int rt,int ll,int rr)
{
    if(ll<=l&&r<=rr) return bmin[rt];
    int mid=l+(r-l)/2;
    int ans=INF;
    if(ll<=mid) ans=min(ans,findmin(l,mid,rt*2,ll,rr));
    if(rr>mid) ans=min(ans,findmin(mid+1,r,rt*2+1,ll,rr));
    return ans;
}
int main()
{
    int len;
    char k[10];
    char fun[10];

    scanf("%d%d",&n,&c);
    for(int i=1;i<=n;++i)
        scanf("%d%d",&a[i],&b[i]);
    buildtree(1,n,1);
    while(c--)
    {
        int ans=0;
        scanf("%s%s%d",k,fun,&len);
        for(int i=1;i<=n;++i)
        {
            int le=lower_bound(a+1,a+1+n,a[i]-len)-a;
            int ri=lower_bound(a+1,a+1+n,a[i])-a;
            ri--;
            if(le>ri) continue;
            if(fun[1]=='i')
            {
                int mmin=findmin(1,n,1,le,ri);
                //cout<mmin) ans++;
                }
                else
                {
                    if(b[i]ave) ans++;
                }
                else
                {
                    if(b[i]mmax) ans++;
                }
                else
                {
                    if(b[i]

 

你可能感兴趣的:(线段树)