[bzoj2827]千山鸟飞绝【splay】

[题目描述]

2827: 千山鸟飞绝

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 815  Solved: 231
[Submit][Status][Discuss]

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的非负整数。


Source

[题解]

每个位置开一个splay,加入时先更新原树答案(打tag),在更新这个点,最后再加入

/* --------------
    user Vanisher
    problem bzoj-2827
----------------*/
# include <bits/stdc++.h>
# define 	N 		400010
# define 	ll 		long long
using namespace std;
int read(){
	int tmp=0, fh=1; char ch=getchar();
	while (ch<'0'||ch>'9'){if (ch=='-') fh=-1; ch=getchar();}
	while (ch>='0'&&ch<='9'){tmp=tmp*10+ch-'0'; ch=getchar();}
	return tmp*fh;
}
struct point{int x,y;}now;
struct node{int w,p;}p[N];
struct Tree{
	int pl,pr,tagi,tagj,fa;
	point num;
}T[N];
int ansi[N],ansj[N],rt[N],place,ti,size[N],n,m,at[N];
map <point, int> mp;
bool operator <(point x, point y){return x.x<y.x||x.x==y.x&&x.y<y.y;}
bool operator ==(point x, point y){return x.x==y.x&&x.y==y.y;}
void pushtag(int x){
	ansi[T[x].num.y]=max(ansi[T[x].num.y],T[x].tagi);
	ansj[T[x].num.y]=max(ansj[T[x].num.y],T[x].tagj);
	T[T[x].pl].tagi=max(T[T[x].pl].tagi,T[x].tagi);
	T[T[x].pl].tagj=max(T[T[x].pl].tagj,T[x].tagj);
	T[T[x].pr].tagi=max(T[T[x].pr].tagi,T[x].tagi);
	T[T[x].pr].tagj=max(T[T[x].pr].tagj,T[x].tagj);
	T[x].tagi=0; T[x].tagj=0;
}
void zig(int x){
	int y=T[x].fa;
	pushtag(y); pushtag(x);
	if (T[T[y].fa].pl==y) 
		T[T[y].fa].pl=x; else T[T[y].fa].pr=x;
	T[x].fa=T[y].fa;
	T[y].pl=T[x].pr; T[T[x].pr].fa=y;
	T[x].pr=y; T[y].fa=x;
}
void zag(int x){
	int y=T[x].fa;
	pushtag(y); pushtag(x);
	if (T[T[y].fa].pl==y) 
		T[T[y].fa].pl=x; else T[T[y].fa].pr=x;
	T[x].fa=T[y].fa;
	T[y].pr=T[x].pl; T[T[x].pl].fa=y;
	T[x].pl=y; T[y].fa=x;
}
void splay(int p, int x){
	int root=rt[p];
	if (x==root) return;
	while (T[x].fa!=root){
		int y=T[x].fa;
		if (T[y].fa==root)
			if (T[y].pl==x) zig(x); else zag(x);
		else if (T[T[y].fa].pl==y)
			if (T[y].pl==x) zig(y), zig(x);
				else zag(x), zig(x);
			else if (T[y].pl==x) zig(x), zag(x);
				else zag(y), zag(x);	
	}
	if (T[root].pl==x) zig(x); else zag(x);
	rt[p]=x;
}
void extend(int p, point x){
	int now=++place;
	at[x.y]=now;
	T[now].num=x;
	size[p]++;
	if (size[p]==1){
		rt[p]=now;
		return;
	}
	T[rt[p]].tagi=max(T[rt[p]].tagi,size[p]-1);	
	int i=rt[p],las=0; point mx;
	while (i!=0){
		mx=T[i].num;
		i=T[i].pr;
	}
	ansj[x.y]=max(ansj[x.y],mx.x);
	ansi[x.y]=max(ansi[x.y],size[p]-1);
	T[rt[p]].tagj=max(T[rt[p]].tagj,x.x);
	las=0, i=rt[p];
	while (i!=0){
		pushtag(i); las=i;
		if (T[i].num<x) i=T[i].pr; else i=T[i].pl;
	}
	if (T[las].num<T[now].num)
		T[las].pr=now; else T[las].pl=now;
	T[now].fa=las;
	splay(p,now);
}
void del(int p, point x){
	int i=rt[p];
	while (i!=0){
		pushtag(i); 
		if (T[i].num==x) break;
		if (T[i].num<x) i=T[i].pr; else i=T[i].pl;
	}
	splay(p,i);
	int l=T[rt[p]].pl,r=T[rt[p]].pr;
	T[l].fa=0; T[r].fa=0;
	if (l==0&&r==0) rt[p]=0;
		else if (l==0) rt[p]=r;
			else if (r==0) rt[p]=l;
				else {
					rt[p]=l;
					int las=0;
					while (l!=0){
						pushtag(l); las=l;
						l=T[l].pr;
					}
					splay(p,las);
					T[rt[p]].pr=r;
					T[r].fa=rt[p];
				}
	size[p]--;
}
int main(){
	n=read();
	for (int i=1; i<=n; i++){
		p[i].w=read(), now.x=read(), now.y=read();
		if (mp.find(now)==mp.end()) mp[now]=++ti;
		p[i].p=mp[now];
		extend(p[i].p,(point){p[i].w,i});
	}
	m=read();
	for (int i=1; i<=m; i++){
		int j=read(); now.x=read(),	now.y=read(); 
		if (mp.find(now)==mp.end()) mp[now]=++ti;
		int nex=mp[now];
		del(p[j].p,(point){p[j].w,j});
		extend(nex,(point){p[j].w,j});
		p[j].p=nex;
	}
	for (int i=1; i<=n; i++){
		splay(p[i].p,at[i]);
		pushtag(rt[p[i].p]);
		printf("%lld
",(ll)ansi[i]*ansj[i]);
	}
	return 0;
}


原文地址:https://www.cnblogs.com/Vanisher/p/9136049.html