CFGym 101505I ——Suspicious Samples (线段树区间查询+二分+英语)

一道纯英语阅读题+线段树模板题(当然读懂了题才是~~)

题面太长,就不放出来了。

题意:给出N(最大1e5)组数据,每组数据包括一个 Ti [1,1e9] 和 Vi [1,1e4] ,其中Ti表示时间且严格递增,Vi代表该点的Val值,给出C [1,10] 个操作,每个操作包括 R(gt,lt),F(min,max,avg),L(int型整数)三个参数,比如输入的是 lt min 100,表示若某结点 i [1,N] 在时间范围为 [T[i]-100,T[i]) 注意开闭区间  的所有组数据中的最小值比V[i] 还小,则ans++;如果是 gt min 100,表示若某结点 i [1,N] 在时间范围为 [T[i]-100,T[i]) 注意开闭区间  的所有组数据中的最小值比V[i] 大,则ans++;其他情况以此类推。

思路:看懂题意后就知道是个简单的区间查询最值和区间求和的问题(对于求平均值直接换成求和就好),然后建三个线段树,分别记录区间min,max和sum就好了,详细看代码。

#include<stdio.h>
#include<algorithm>
#include<string.h>
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
using namespace std;
typedef long long ll;
const int maxn=1e5+5;
int T[maxn],V[maxn];
struct node
{
    int Max,Min,Sum;
}tree[maxn<<2];

void push_up(int rt)
{
    tree[rt].Min=min(tree[rt<<1].Min,tree[rt<<1|1].Min);
    tree[rt].Max=max(tree[rt<<1].Max,tree[rt<<1|1].Max);
    tree[rt].Sum=tree[rt<<1].Sum+tree[rt<<1|1].Sum;
}

void build(int l,int r,int rt)
{
    if(l==r)
    {
        scanf("%d%d",&T[l],&V[l]);
        tree[rt].Max=V[l];
        tree[rt].Min=V[l];
        tree[rt].Sum=V[l];
        return;
    }
    int mid=(l+r)>>1;
    build(lson);
    build(rson);
    push_up(rt);
}

int querymin(int L,int R,int l,int r,int rt)
{
    if(L<=l&&R>=r)
    {
        return tree[rt].Min;
    }
    int mid=(l+r)>>1;
    int ret=1e9;
    if(L<=mid) ret=min(ret,querymin(L,R,lson));
    if(R>mid)  ret=min(ret,querymin(L,R,rson));
    return ret;
}

int querymax(int L,int R,int l,int r,int rt)
{
    if(L<=l&&R>=r)
    {
        return tree[rt].Max;
    }
    int mid=(l+r)>>1;
    int ret=-1;
    if(L<=mid) ret=max(ret,querymax(L,R,lson));
    if(R>mid)  ret=max(ret,querymax(L,R,rson));
    return ret;
}

int querysum(int L,int R,int l,int r,int rt)
{
    if(L<=l&&R>=r)
    {
        return tree[rt].Sum;
    }
    int mid=(l+r)>>1;
    int ret=0;
    if(L<=mid) ret+=(ret,querysum(L,R,lson));
    if(R>mid)  ret+=(ret,querysum(L,R,rson));
    return ret;
}

int main()
{
    int n,m;
    while(~scanf("%d",&n))
    {
        build(1,n,1);
        scanf("%d",&m);
        char S1[5],S2[5];
        int d,s,t,temp,ans;
        while(m--)
        {
            scanf("%s%s%d",S1,S2,&d);
            ans=0;
            if(strcmp(S2,"min")==0)
            {
                for(t=2;t<=n;t++)         //依次在【s,t】区间查找
                {
                    temp=max(1,T[t]-d);    //注意减后为负数的情况
                    s=lower_bound(T+1,T+1+n,temp)-T;
                    if(s>t-1) continue;    //位置不合法跳过
                    if(S1[0]=='g') ans+=(V[t]>querymin(s,t-1,1,n,1));
                    else           ans+=(V[t]<querymin(s,t-1,1,n,1));
                }
            }
            else if(strcmp(S2,"max")==0)
            {
                for(t=2;t<=n;t++)
                {
                    temp=max(1,T[t]-d);
                    s=lower_bound(T+1,T+1+n,temp)-T;
                    if(s>t-1) continue;
                    if(S1[0]=='g') ans+=(V[t]>querymax(s,t-1,1,n,1));
                    else           ans+=(V[t]<querymax(s,t-1,1,n,1));
                }
            }
            else if(strcmp(S2,"avg")==0)
            {
                for(t=2;t<=n;t++)
                {
                    temp=max(1,T[t]-d);
                    s=lower_bound(T+1,T+1+n,temp)-T;
                    if(s>t-1) continue;
                    if(S1[0]=='g') ans+=(V[t]*(t-s)>querysum(s,t-1,1,n,1));
                    else           ans+=(V[t]*(t-s)<querysum(s,t-1,1,n,1));
                }
            }
            printf("%d\n",ans);
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/QuincyTan/article/details/81610909
今日推荐