nyoj 1286 找出第二大

找出第二大

时间限制: 4000 ms  |  内存限制: 65535 KB
难度: 4
描述

给你n个数,然后询问你m次。每次询问只有两种情况:

         Q  L  R :       输出 L R 区间内第二大的值(与第一大的值相同的不算第二大)如果没有第二大的值,输出-1
         S  L  R  K  :  L
R 区间内,每个值减去 K
输入
第1行输入n,m. 0<n,m,<=100000
第2行是n个整数ai, -1000000<=ai<=1000000
第3到第m+2,每行一个对应的操作。1<=l<=r<=n。 -1000000<=k<=1000000
输出
对于每个Q操作,输出答案。保证所有数据在int范围内(那为什么还把值弄得那么大呢?(~ ̄▽ ̄)~)
样例输入
  5 6  1 1 1 2 3  Q 1 3   Q 4 5  Q 4 4  S 1 1 1  Q 1 3  Q 1 5
样例输出
-12-102
来源
cszdlt
上传者

传说中的蓝天



 如过是找出最大的就是用线段树写,找出第二的也是可以用线段树写,  每个节点存两个值一个为最大值 ,一个为次大值,这样父亲节点的最大值就是左右两个儿子较大的那个,次大值就是左右两个儿子 最大的和次大的4 个数中不同于最大值的那个值。 


#include<bits/stdc++.h>
using namespace std;
const int N = 100010;
const int ing = 0x3f3f3f3f;
const int   inf = -ing;
int   ma[N<<2];
int  mx[N<<2];
int   add[N<<2];
int   a[N];
bool cmp(int  f ,int   g)
{
    return f>g;
}
void push_up(int  rt)
{
    ma[rt] = max(ma[rt<<1],ma[rt<<1|1]);
    int   t[10];
    t[1] = ma[rt<<1];
    t[2] = ma[rt<<1|1];
    t[3] = mx[rt<<1];
    t[4] = mx[rt<<1|1];
    mx[rt] = inf;
    if(t[1]>t[2])
    {
        mx[rt] = t[2];
        mx[rt] = max(t[3],mx[rt]);

    }
    else if(t[1]<t[2])
    {
        mx[rt] = t[1];
        mx[rt] = max(mx[rt],t[4]);

    }
    else
    {
        if(t[3]!=t[4])
        {
            mx[rt] = max(t[3],t[4]);
        }
        else
        {
             if(t[3]!=t[1])
             {
                  mx[rt] = t[3];
             }
        }
    }
}
int max(int a,int b)
{
    return a>b?a:b;
}
void push_down(int rt)
{
    if(add[rt]!=0)
    {
        add[rt<<1]+=add[rt];
        add[rt<<1|1]+=add[rt];
        ma[rt<<1]+=add[rt];
        ma[rt<<1|1]+=add[rt];
        if(mx[rt<<1]!=inf)
            mx[rt<<1]+=add[rt];
        if(mx[rt<<1|1]!=inf)
            mx[rt<<1|1]+=add[rt];
        add[rt] = 0;
    }
}
void update(int L,int R,int l,int r,int rt,int  k)
{
    if(L<=l&&r<=R)
    {
        if(mx[rt]!=inf)
            mx[rt]+=k;
        ma[rt]+=k;
        add[rt]+=k;
        return;
    }
    push_down(rt);
    int mid = (l+r)>>1;
    if(L<=mid)
        update(L,R,l,mid,rt<<1,k);
    if(R>mid)
        update(L,R,mid+1,r,rt<<1|1,k);
    push_up(rt);
}
int query1(int  L ,int R ,int l ,int r ,int rt)
{
    if(L<=l&&r<=R)
    {
        return ma[rt];
    }
    push_down(rt);
    int mid = (l+r)>>1;
    int  k = inf;
    int   g = inf;
    if(L<=mid)
        k = query1(L ,R ,l ,mid,rt<<1);
    if(R>mid)
        g = query1(L ,R ,mid+1,r, rt<<1|1);
    return max (k,g);
}
int  query(int L ,int R ,int l ,int r ,int rt)
{
    if(L<=l&&r<=R)
    {
        return mx[rt];
    }
    push_down(rt);
    int   w[5];
    for(int i = 1 ; i<=4; i++)
        w[i] = inf;
    int mid = (l+r)>>1;
    int fg = inf;
    int ans = inf;
    if(L<=mid)
    {
        w[3] = query1(L ,R ,l ,mid,rt<<1);
        fg = max(fg,w[3]);
    }
    if(R>mid)
    {
        w[4] = query1(L ,R ,mid+1,r,rt<<1|1);
        fg = max(fg,w[4]);
    }
    if(w[3]!=fg)
        ans = max(ans,w[3]);
    if(w[4]!=fg)
        ans = max(ans,w[4]);
    if(L<=mid)
    {
        w[1] =query(L ,R,l ,mid,rt<<1);
        if(w[1]!=fg)
            ans= max(ans,w[1]);
    }
    if(R>mid)
    {
        w[2] = query(L ,R, mid+1,r,rt<<1|1);
        if(w[2]!=fg)
            ans = max(ans,w[2]);
    }
    return ans;
}
void bulid(int l,int r,int rt)
{
    if(l==r)
    {
        scanf("%d",&a[l]);
        ma[rt] = a[l];
        mx[rt] = inf;
        add[rt] = 0;
        return ;
    }
    add[rt]  = 0;
    int mid = (l+r)>>1;
    bulid(l,mid,rt<<1);
    bulid(mid+1,r,rt<<1|1);
    push_up(rt);
}
char s[10];
int main()
{
    int n, m;
    while(scanf("%d%d",&n,&m)!=EOF)
    {

        bulid(1,n,1);
        for(int  i = 1; i<=m; i++)
        {
            scanf("%s",&s);
            int L ,R;
            int  k;
            if(s[0]=='S')
            {
                scanf("%d%d%d",&L,&R,&k);
                update(L,R,1,n,1,-k);
            }
            else
            {
                scanf("%d%d",&L,&R);
                int  kg = query(L ,R ,1 ,n ,1);
                if(kg ==inf)
                    printf("-1\n");
                else
                    printf("%d\n",kg);
            }
        }
    }
    return 0;
}        


猜你喜欢

转载自blog.csdn.net/theflowerofac/article/details/52368409
今日推荐