标签:
一个求最大值和次大值的问题。
在更新的时候将两个子区间的最大次大值都算进去,排个序再装进去即可。
#include<iostream>
#include<cstdio>
#include<algorithm>
#define maxn 800005
using namespace std;
struct tree
{
int left,right;
int value1,value2;
}node[maxn];
struct ans
{
int a,b;
};
int n,q,father[maxn],type,x,y;
void build(int i,int left,int right)
{
node[i].left=left;
node[i].right=right;
node[i].value1=0;
node[i].value2=0;
if (left==right)
{
father[left]=i;
return;
}
else
{
int mid=(left+right)>>1;
i=i<<1;
build(i,left,mid);
build(i+1,mid+1,right);
}
}
void modify(int x)
{
int fath=x>>1,a[5];
int ls=fath<<1,rs=(fath<<1)+1;
a[1]=node[ls].value1;
a[2]=node[ls].value2;
a[3]=node[rs].value1;
a[4]=node[rs].value2;
sort(a+1,a+5);
node[fath].value1=a[4];
node[fath].value2=a[3];
if (fath==1) return;
else modify(fath);
}
ans ask(int i,int l,int r)
{
int left=node[i].left,right=node[i].right;
int value1=node[i].value1,value2=node[i].value2;
if ((left==l) && (right==r))
{
ans tk;
tk.a=node[i].value1;
tk.b=node[i].value2;
return tk;
}
else
{
int mid=(left+right)>>1;
if (r<=mid)
return ask(i<<1,l,r);
else if (l>=mid+1)
return ask((i<<1)+1,l,r);
else
{
ans tk,yk,rep;
tk=ask(i<<1,l,mid);
yk=ask((i<<1)+1,mid+1,r);
int a[5];
a[1]=tk.a;a[2]=tk.b;
a[3]=yk.a;a[4]=yk.b;
sort(a+1,a+5);
rep.a=a[4];rep.b=a[3];
return rep;
}
}
}
int main()
{
scanf("%d%d",&n,&q);
build(1,1,n);
for (int i=1;i<=q;i++)
{
scanf("%d%d%d",&type,&x,&y);
if (type==1)
{
node[father[x]].value1+=y;
modify(father[x]);
}
else
{
ans k=ask(1,x,y);
printf("%d\n",k.a-k.b);
}
}
return 0;
}
标签:
原文地址:http://www.cnblogs.com/ziliuziliu/p/5156065.html