【BZOJ2827】千山鸟飞绝 hash+堆+SBT

【BZOJ2827】千山鸟飞绝

Description

话说有一天doyouloveme和vfleaking到山里玩。谁知doyouloveme刚刚进山,所有的鸟儿竟被他的神犇气场给惊得全部飞走了。vfleaking顿时膜拜不已。
这时鸟王用鸟语说道:“!@#$%……?”安抚了一下众鸟的情绪。鸟王生性好斗,作出了一个决定——要排鸟布阵把刚才吓到它们的人类赶出山去。
每只鸟都有一个编号,都有一个威武值。每秒钟鸟王都会发一个命令,编号为v的鸟飞到(x,y)去(坐标系原点是山顶,坐标单位为鸟爪)。鸟飞得很快,一秒之内就飞到了,可以看作是瞬间移动。如果编号为v的鸟和编号为u的鸟某一时刻处在同一位置,它们就会互相鼓励,增加各自的士气值和团结值。一只鸟的士气值等于此刻与它处在同一位置的鸟中的威武值的最大值,团结值等于此刻与它处在同一位置的鸟的只数。如果每一时刻都没有鸟与它处在同一位置,则士气值和团结值都为0。要注意自己不能鼓励自己,计算士气值和团结值时不能算上自己。
t秒钟后,doyouloveme目测出了现在每只鸟的战斗力,于是感叹了一句:“不妙,我们得走了。”
正所谓团结的鸟儿一个顶俩,所以doyouloveme这样描述战斗力:一只鸟战斗力值等于它在0到t秒中士气值的最大值与团结值的最大值的乘积。注意不是乘积的最大值,而是最大值的乘积。
vfleaking很想知道现在每只鸟的战斗力,但是他当然不会啦,于是他把这个任务交给了你来完成。

Input

第一行一个数n,代表鸟的只数。(鸟王那家伙你可以完全忽视掉)
接下来n行,每行三个整数w,x,y描述每只鸟的威武值和初始坐标。第i+1行描述编号为i的鸟。
接下来一行有一个数t,代表经过时间ts。
接下来t行,每行三个整数v,x,y描述鸟王每秒的命令。

Output

一共n行,每行一个数,代表每只鸟的战斗力。

Sample Input

5
1 1 1
3 1 2
4 4 4
2 0 1
2 2 3
5
1 1 2
2 4 4
2 4 3
3 0 1
5 0 1

Sample Output

3
4
6
8
8

HINT

对于样例的解释:
首先5只鸟的位置为(1,1),(1,2),(4,4),(0,1),(2,3),士气和团结值都是0。
鸟1飞到了(1,2),于是鸟1和鸟2互相鼓励,鸟1士气变为3,鸟2士气变为1。鸟1鸟2的团结值变为1。
然后鸟2飞到(4,4),与鸟3互相鼓励,鸟2士气变为4,鸟3士气变为3。鸟2与鸟3的团结值变为1。
鸟2然后飞到了(4,3),一个没有鸟的地方。于是士气和团结值都变为了0。
接下来鸟3和鸟5都飞到了鸟4的位置,于是三只鸟互相鼓励,鸟4、鸟5士气变为4,鸟3士气仍为3。鸟3、鸟4、鸟5的团结值都变为2。
于是大家的战斗力:
鸟1:3 * 1 = 3
鸟2:4 * 1 = 4
鸟3:3 * 2 = 6
鸟4:4 * 2 = 8
鸟5:4 * 2 = 8
1≤n≤30000   0≤t≤300000   坐标范围为整数,且不超过INT_MIN~INT_MAX
威武值为不超过INT_MAX的非负整数。

题解:容易想到hash,将坐标相同的鸟都放到一起,用一个数据结构维护一下,这个数据结构需要维护以下操作:

插入,删除,统计个数;
统计权值最大值和次大值,以及其编号;
用最大值更新其它点的答案,用次大值更新最大值的答案。

可以用可删除堆维护最大值和次大值,其余的用SBT打标记维护。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <vector>
#include <queue>
using namespace std;
typedef long long ll;
const int maxn=30010;
const ll P=999983;
int n,m,tot;
int s1[maxn],s2[maxn],v[maxn],rt[maxn*11],X[maxn],Y[maxn];
bool vis[maxn*11];
struct node
{
	int ch[2],siz,org,t1,t2;
}s[maxn];
struct pt
{
	int x,y,num;
	pt() {}
	pt(int a,int b,int c) {x=a,y=b,num=c;}
};
vector<pt> hs[999990];
struct Num
{
	int x;
	Num() {}
	Num(int a) {x=a;}
	bool operator < (const Num &b) const
	{
		return v[x]<v[b.x];
	}
};
struct heap
{
	priority_queue<Num> p1,p2;
	inline int top()
	{
		while(!p2.empty()&&p1.top().x==p2.top().x)	p1.pop(),p2.pop();
		return (p1.empty())?0:p1.top().x;
	}
	inline int top2()
	{
		int x=top();
		if(p1.empty())	return 0;
		p1.pop();
		int y=top();	p1.push(Num(x));
		return y;
	}
	inline void erase(int x)	{p2.push(Num(x));}
	inline void push(int x)	{p1.push(Num(x));}
}p[maxn*11];
inline int point(int x,int y)
{
	ll val=((((ll(x)<<20)+y)^((ll(y)<<10)+x))%P+P)%P;
	int i;
	for(i=0;i<(int)hs[val].size();i++)	if(hs[val][i].x==x&&hs[val][i].y==y)	return hs[val][i].num;
	hs[val].push_back(pt(x,y,++tot));
	return tot;
}
inline void upd(int x,int t1,int t2)
{
	s1[s[x].org]=max(s1[s[x].org],t1),s2[s[x].org]=max(s2[s[x].org],t2);
	s[x].t1=max(s[x].t1,t1),s[x].t2=max(s[x].t2,t2);
}
inline void pushdown(int x)
{
	if(s[x].t1||s[x].t2)
	{
		if(s[x].ch[0])	upd(s[x].ch[0],s[x].t1,s[x].t2);
		if(s[x].ch[1])	upd(s[x].ch[1],s[x].t1,s[x].t2);
		s[x].t1=s[x].t2=0;
	}
}
inline void pushup(int x)
{
	s[x].siz=s[s[x].ch[0]].siz+s[s[x].ch[1]].siz+1;
}
inline void rotate(int &x,int d)
{
	int y=s[x].ch[d];
	pushdown(x),pushdown(y);
	s[x].ch[d]=s[y].ch[d^1],s[y].ch[d^1]=x;
	pushup(x),pushup(y);
	x=y;
}
inline void maintain(int &x,int d)
{
	if(s[s[s[x].ch[d]].ch[d]].siz>s[s[x].ch[d^1]].siz)	rotate(x,d);
	else	if(s[s[s[x].ch[d]].ch[d^1]].siz>s[s[x].ch[d^1]].siz)	rotate(s[x].ch[d],d^1),rotate(x,d);
	else	return ;
	maintain(s[x].ch[d],d),maintain(s[x].ch[d^1],d^1);
	maintain(x,d),maintain(x,d^1);
}
void insert(int &x,int y)
{
	if(!x)
	{
		x=y,s[x].siz=1,s[x].ch[0]=s[x].ch[1]=s[x].t1=s[x].t2=0;
		return ;
	}
	pushdown(x);
	int d=(s[y].org>s[x].org);
	insert(s[x].ch[d],y),pushup(x);
	maintain(x,d);
}
int del(int &x,int y)
{
	pushdown(x),s[x].siz--;
	if(s[x].org==y)
	{
		if(!s[x].ch[0]||!s[x].ch[1])
		{
			int u=x;
			x=s[x].ch[0]^s[x].ch[1];
			return u;
		}
		int u=s[x].ch[1];
		pushdown(u);
		while(s[u].ch[0])	u=s[u].ch[0],pushdown(u);
		s[x].org=s[u].org;
		return del(s[x].ch[1],s[u].org);
	}
	if(s[x].org>y)	return del(s[x].ch[0],y);
	return del(s[x].ch[1],y);
}
void updata(int x,int t1,int t2)
{
	if(!x)	return ;
	pushdown(x);
	if(s[x].org<=t1)	upd(s[x].ch[0],v[t1],0);
	if(s[x].org>=t1)	upd(s[x].ch[1],v[t1],0);
	if(s[x].org==t1)	s1[s[x].org]=max(s1[s[x].org],v[t2]);
	else	s1[s[x].org]=max(s1[s[x].org],v[t1]),updata(s[x].ch[t1>s[x].org],t1,t2);
}
inline int rd()
{
	int ret=0,f=1;	char gc=getchar();
	while(gc<'0'||gc>'9')	{if(gc=='-')	f=-f;	gc=getchar();}
	while(gc>='0'&&gc<='9')	ret=ret*10+(gc^'0'),gc=getchar();
	return ret*f;
}
inline void add(int x,int y,int a,int b)
{
	int pos=point(a,b);
	s[y].org=x,insert(rt[pos],y);
	p[pos].push(x);
	upd(rt[pos],0,s[rt[pos]].siz-1);
	updata(rt[pos],p[pos].top(),p[pos].top2());
}
inline int rem(int x,int a,int b)
{
	int pos=point(a,b),y=del(rt[pos],x);
	p[pos].erase(x);
	return y;
}
void dfs(int x)
{
	if(!x)	return ;
	pushdown(x);
	dfs(s[x].ch[0]),dfs(s[x].ch[1]);
}
int main()
{
	n=rd();
	int i,a,b;
	for(i=1;i<=n;i++)
	{
		v[i]=rd(),X[i]=rd(),Y[i]=rd();
		add(i,i,X[i],Y[i]);
	}
	m=rd();
	for(i=1;i<=m;i++)
	{
		a=rd(),b=rem(a,X[a],Y[a]);
		X[a]=rd(),Y[a]=rd(),add(a,b,X[a],Y[a]);
	}
	for(i=1;i<=n;i++)
	{
		a=point(X[i],Y[i]);
		if(!vis[a])	vis[a]=1,dfs(rt[a]);
	}
	for(i=1;i<=n;i++)	printf("%lld
",(ll)s1[i]*s2[i]);
	return 0;
}//5 1 1 1 3 1 2 4 4 4 2 0 1 2 2 3 5 1 1 2 2 4 4 2 4 3 3 0 1 5 0 1 
原文地址:https://www.cnblogs.com/CQzhangyu/p/7812915.html