题目描述
第一行为两个整数N,Q,以空格隔开。
接下来Q行,每行代表一个事件。第i+1行代表第i个事件,这一行有三个整数Ci,Xi,Yi,其中Ci为1或2。如果Ci为1,表示在城市Xi又新发现了Yi个病例;如果Ci为2,表示询问从Xi到Yi,病例最多的城市与病例第二多的城市的病例数之差为多少。
输出描述
对于输入中的每一个Ci=2的事件,输出一行,即询问的结果。
样例输入
4
2 1 4
1 2 3
2 2 4
1 3 2
2 1 3
1 2 2
2 1 4
样例输出
0
3
1
3
数据范围及提示
【样例说明】
初始时各个城市的病例数为{0,0,0,0}。
从1到4最多的病例数为0,第二多的病例数为0,差值为0,输出0。
城市2发现了3个新病例,病例数变为{0,3,0,0}。
从2到4最多的病例数为3,第二多的病例数为0,差值为3,输出3。
城市3发现了2个新病例,病例数变为{0,3,2,0}。
从1到3最多的病例数为3,第二多的病例数为2,差值为1,输出1。
城市2发现了2个新病例,病例数变为{0,5,2,0}。
从1到4最多的病例数为5,第二多的病例数为2,差值为3,输出3。
【数据规模与约定】
对于40%的数据,N,Q≤1000。
对于100%的数据,2≤N,Q≤100000,且对于每一个Ci=2,满足Xi<Yi。
题解:这道是线段树求最大值的小变形。要求区间内的最大值和第二大值。我们在修改时记录最大值和第二大值时即可,查询时将所大区间内的最大值和第二大值记录一下即可。
#include <cstdio>
#include <algorithm>
int n,q,x,y,z,xx,t=0,maxn=0,maxn1=0;
char ch;
bool bo;
struct TREE{
int l,r,maxx,sec;
}tree[400005];
using namespace std;
inline int read()
{
int f=1,x=0;
char ch=getchar();
if (ch=='-')
{
f=-1;
ch=getchar();
}
while ((ch<'0')||(ch>'9')) ch=getchar();
while ((ch>='0')&&(ch<='9'))
{
x=x*10+ch-48;
ch=getchar();
}
return f*x;
}
inline void build(int root,int l,int r)
{
tree[root].l=l,tree[root].r=r;
if (l==r)
{
tree[root].sec=-1;
return;
}
build(root*2,l,(l+r)/2);
build(root*2+1,(l+r)/2+1,r);
}
inline void change(int root,int x)
{
int ll=tree[root].l,rr=tree[root].r;
if ((ll==x)&&(rr==x))
{
tree[root].maxx+=z;
return;
}
if (x<=(ll+rr)/2) change(root*2,x); else change(root*2+1,x);
tree[root].maxx=max(tree[root<<1].maxx,tree[root<<1|1].maxx);
if (tree[root*2].maxx>tree[root*2+1].maxx)
tree[root].sec=max(tree[root*2+1].maxx,tree[root*2].sec);
if (tree[root*2].maxx<tree[root*2+1].maxx)
tree[root].sec=max(tree[root*2+1].sec,tree[root*2].maxx);
if (tree[root*2].maxx==tree[root*2+1].maxx)
tree[root].sec=tree[root*2].maxx;
}
inline void find(int root,int l,int r)
{
int ll=tree[root].l,rr=tree[root].r;
int mid=(ll+rr)/2;
if ((l<=ll)&&(rr<=r))
{
if (tree[root].maxx>maxn1) maxn1=tree[root].maxx;
if (tree[root].maxx>maxn)
{
maxn1=maxn;
maxn=tree[root].maxx;
}
if (tree[root].sec>maxn1) maxn1=tree[root].sec;
if (tree[root].sec>maxn)
{
maxn1=maxn;
maxn=tree[root].sec;
}
return;
}
if (l<=(ll+rr)/2) find(root*2,l,r);
if (r>(ll+rr)/2) find(root*2+1,l,r);
}
int main()
{
//freopen("1.in","r",stdin);
n=read();q=read();
build(1,1,n);
for (int i=1;i<=q;i++)
{
x=read(),y=read(),z=read();
if (x==1) change(1,y);
else
{
maxn=0,maxn1=0;
find(1,y,z);
printf("%d\n",maxn-maxn1);
}
}
return 0;
}