CODEVS 2018 反病毒软件

题目描述 

第一行为两个整数NQ,以空格隔开。

接下来Q行,每行代表一个事件。第i+1行代表第i个事件,这一行有三个整数CiXiYi,其中Ci12。如果Ci1,表示在城市Xi又新发现了Yi个病例;如果Ci2,表示询问从XiYi,病例最多的城市与病例第二多的城市的病例数之差为多少。

输出描述

对于输入中的每一个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

数据范围及提示

【样例说明】

初始时各个城市的病例数为{0000}

14最多的病例数为0,第二多的病例数为0,差值为0,输出0

城市2发现了3个新病例,病例数变为{0300}

24最多的病例数为3,第二多的病例数为0,差值为3,输出3

城市3发现了2个新病例,病例数变为{0320}

13最多的病例数为3,第二多的病例数为2,差值为1,输出1

城市2发现了2个新病例,病例数变为{0520}

14最多的病例数为5,第二多的病例数为2,差值为3,输出3

 【数据规模与约定】

对于40%的数据,NQ1000

对于100%的数据,2NQ100000,且对于每一个Ci=2,满足XiYi

题解:这道是线段树求最大值的小变形。要求区间内的最大值和第二大值。我们在修改时记录最大值和第二大值时即可,查询时将所大区间内的最大值和第二大值记录一下即可。

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

猜你喜欢

转载自blog.csdn.net/zhouhongkai06/article/details/80371409