题目描述
第一行为两个整数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; }