n个城市,点修改,区间询问最大值与第二大值之差,很明显的线段树。此题有点水。
求最大值与第二大值之差,就维护最大值与第二大的值,每次修改时更新值。
设最大值为fir,第二大为sec,如果x<sec则不修改,如果x>fir,把fir变成x,sec变成fir,如果fir<x<sec,sec=x;
这样子看上去好像对了,但实际上会WA,为什么呢?这样子做的话会出现这种情况:
1-5: fir:5(3号城市) sec:2(1号城市)
如果再对于3号城市加上3,那么因为5+3=8>5(fir) sec=5,fir=8(都是3号城市,但sec是历史值),就不是第一、二大的城市之差。
所以还应该记录第一、二大值所在城市,如果x>fir,并且城市相同,直接fir=x。
查询时全局设变量maxn,secn,记录当前查询到的第一、二大的值,并且每次查询前初始化为0。
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <string>
#include <queue>
#include <climits>
#include <ctime>
#include <stack>
#include <iostream>
using namespace std;
int maxn=0,secn=0;
class node{
public:
int l,r,fir,sec,fc,sc;
node *lt,*rt;
node(){
l=0,r=0,fir=0,sec=0,fc=0,sc=0;
lt=NULL,rt=NULL;
}
void build(int ll,int rr)
{
l=ll,r=rr;
if(rr-ll>1){
int mid=(l+r)>>1;
lt=new node;
lt->build(ll,mid);
rt=new node;
rt->build(mid,rr);
}
}
int insert(int num,int inc)
{
if(num==l &&num+1==r){fir+=inc;return fir;}
int mid=(l+r)>>1,tmp;
if(num<mid) tmp=lt->insert(num,inc);
if(num>=mid) tmp=rt->insert(num,inc);
if(tmp==0 || tmp<=sec) return 0;
if(tmp>fir){
if(fc==num) fir=tmp;
else{
sc=fc,sec=fir;
fc=num,fir=tmp;
}
}
else sec=tmp,sc=num;
return tmp;
}
void que(int ll,int rr){
if(ll==l && r==rr){
if(sec>maxn) secn=maxn,maxn=sec;
else if(sec>secn) secn=sec;
if(fir>maxn) secn=maxn,maxn=fir;
else if(fir>secn) secn=fir;
return;
}
int mid=(l+r)>>1;
if(rr<=mid) lt->que(ll,rr);
else if(ll>=mid) rt->que(ll,rr);
else lt->que(ll,mid),rt->que(mid,rr);
}
}*tree;
int n,q;
int main()
{
int x,y,c;
scanf("%d%d",&n,&q);
tree=new node;
tree->build(1,n+1);
for(int i=1;i<=q;i++){
scanf("%d%d%d",&c,&x,&y);
if(c==1) tree->insert(x,y);
else maxn=0,secn=0,tree->que(x,y+1),printf("%d\n",maxn-secn);
}
system("pause");
return 0;
}