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;
}        


版权声明:

相关文章推荐

找出一个整数数组中,第二大的数

/* 写一个函数找出一个整数数组中第二大的数 */#include #include #include #define SIZE 10 int array[] = {0}; //随机产...

如何找出数组中第二大的数

如果仅仅是考虑实现功能,而不考虑时间效率,可以先通过排序算法将数组进行排序,然后根据数组下标来索引访问数组中第二大的数,最快的排序算法一般为快速排序算法,但是其时间复杂度仍未O(nlogn),根据下标...

寻找数组中的第二大数

/* 写一个函数找出一个整数数组中,第二大的数(microsoft) 要求效率尽可能高 */ #include "stdio.h" #include "stdlib.h" int f...

编程之美2.10扩展问题求数组中第二大数

要求求得数组中第二大数采用分治思想解决这个问题 #include using namespace std; //分治思想求数组中第二大的数 //low为数组低位索引,high为数组高位索引 v...

锦标赛(n个数中求第一和第二大的数)

如果要在n个数据中挑选出第一大和第二大的数据(要求输出数据所在位置和值),使用什么方法比较的次数最少?我们可以从体育锦标赛中受到启发。如图【1.png】所示,8个选手的锦标赛,先两两捉对比拼,淘汰一半...

spring心得7--spring第二大特点AOP(面向切面)讲解

本篇博客重点讲解AOP的概念和知识点的介绍,下一篇博客重点通过案例和注释来分析讲解spring aop的通知等概念 1.定义AOP术语   1).切面(aspect):要实现的交叉功能,是系统模块...

【算法】16个无序数最多20次比较找到第二大的数

这个题是刚刚在微博上看到的,第一想法就想到了leetcode上关于注水的题,Trapping Rain Water,当时的解法是这样的:通过求第二大的数,来解决注水问题class Solution {...

查找一个数组中第二大的数的下标并输出

查找一个数组中第二大的数的下标并输出

中国互联网成全球第二大毒源|个人信息值70元

在纽约每3.5分钟就会发生一起犯罪事件,在柏林是2分钟,而在互联网上是0.25秒。赛门铁克消费产品事业部高级市场总监、亚太及日本地区市场营销负责人吴又又透露,根据赛门铁克统计数据显示,全球范围内五分之...

主题演讲:《中国IT外包新视界— 当中国成为世界第二大经济体 》

2011年,中国已经成为世界第二的经济大国。而软件外包产业也将再次迎来新的机遇与挑点。埃尔钦汗先生对全球形势和外包行业有着渊博知识和精确分析,从最大的发包方所在国视角,全面系统地阐明了为什么中国将会成...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

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