nyoj 1286 找出第二大

原创 2016年08月30日 13:26:10

找出第二大

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

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

         Q  L  R :      输出LR区间内第二大的值(与第一大的值相同的不算第二大)如果没有第二大的值,输出-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;
}        


nyoj 1286 找出第二大

找出第二大 时间限制:4000 ms  |  内存限制:65535 KB 难度:4 描述 给你n个数,然后询问你m次。每次询问只有两种情况:          Q  L  R :      输出L到...
  • Theflowerofac
  • Theflowerofac
  • 2016年08月30日 13:26
  • 221

寻找数组中的第二大数

/* 写一个函数找出一个整数数组中,第二大的数(microsoft) 要求效率尽可能高 */ #include "stdio.h" #include "stdlib.h" int f...
  • Hackbuteer1
  • Hackbuteer1
  • 2011年08月01日 16:13
  • 14256

用最少次数找出第二大的数;

比如有16个数,找出第一大和第二大的数; 方法一:先找第一大的15次,再找第二大的14次,15+14 方法二:建立小根堆法,15~29次 方法三:胜者树法,15+3=18次 以下介绍胜者树 第二次...
  • Yan456jie
  • Yan456jie
  • 2016年08月08日 11:41
  • 911

查找数组中第二大的数

方法一:先进行排序,然后直接很具数组下标对倒数第二个数进行查找即可,此时时间复杂度最好为:O(nlogn) 方法二:设置两个变量(一个保存最大的数,一个保存第二大的数)进行判断。对数组进行一边的遍历...
  • YDZXF
  • YDZXF
  • 2015年03月16日 15:34
  • 972

201709-5 除法 ccf

问题描述   小葱喜欢除法,所以他给了你N个数a1, a2, ⋯, aN,并且希望你执行M次操作,每次操作可能有以下两种:   给你三个数l, r, v,你需要将al, al+1, ⋯, ar之间...
  • gl486546
  • gl486546
  • 2017年10月26日 22:26
  • 1414

问题描述 给定一个序列,每次询问序列中第l个数到第r个数中第K大的数是哪个。 输入格式 第一行包含一个数n,表示序列长度。 第二行包含n个正整数,表示给定的序列。 第三个包含一个正整数m,表

#include using namespace std; void print(int *a,int len) { int i=0; for(;i cout cout } void...
  • Faded0104
  • Faded0104
  • 2016年12月30日 20:14
  • 2502

找出数组中的最大和第二大元素需要进行几次比较?

题目:在一个有8个int数据的数组中,随机给出数组的数据,找出最大和第二大元素一定需要进行()次比较? A.8 B.9 C.10 D.11 答案:B 解析:...
  • NumberOneOrNothing
  • NumberOneOrNothing
  • 2017年04月18日 20:46
  • 432

找出数组中第二大的数

题目:写一个函数找出一个整数数组中,第二大的数。 #include //初始化最大值为a[0],次大值为a[1],遍历一次,每次比较并更新最大值和次大值,最后就可以得到次大值。 int fi...
  • lwj103862095
  • lwj103862095
  • 2013年09月24日 20:13
  • 11215

将n个数分为m个数[动态规划][两种思路]

[声明]欢迎讨论,欢迎一起学习 题目: 将n(一个整数)划分成m个(大于等于1的整数)有多少种可能 例如: 5 2         out: 2 (2,3 ; 1,4); 100 33   ...
  • qq_36412483
  • qq_36412483
  • 2017年08月25日 17:30
  • 338

HDU 3333 Turing Tree (离线询问+线段树)

题目地址:HDU 3333 将询问离线保存下来,然后将数组的点离散化,记录每个值上一次出现的位置。然后枚举数组的数,若当前枚举的数前面出现过,那么就删掉前面出现过的那个位置上的数,更新当前这个位置上...
  • u013013910
  • u013013910
  • 2015年05月06日 17:06
  • 673
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:nyoj 1286 找出第二大
举报原因:
原因补充:

(最多只允许输入30个字)