BZOJ2827 千山鸟飞绝

这个……我们会发现,坐标其实没毛卵用,只不过是区分不同的点

所以我们直接把坐标离散化了

然后鸟来回飞就相当于一个维护集合大小,集合max,一个集合里的某个权值对一个数取max

拿个splay随便搞搞就可以了

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<ctime>
#include<cmath>
#include<algorithm>
#include<iomanip>
#include<vector>
#include<map>
#include<set>
#include<bitset>
#include<queue>
#include<stack>
using namespace std;
#define MAXN 330010
#define MAXM 1010
#define INF 1000000000
#define MOD 1000000007
#define eps 1e-8
#define ll long long
int fa[MAXN],son[MAXN][2],v[MAXN],siz[MAXN],v1[MAXN],v2[MAXN],ch1[MAXN],ch2[MAXN],mx[MAXN];
int st[MAXN],tp;
int rt[MAXN];
int bel[MAXN];
int n,m;
map<pair<int,int>,int>h;
int tot;
inline void ud(int x){
	if(!x){
		return ;
	}
	siz[x]=siz[son[x][0]]+siz[son[x][1]]+1;
	mx[x]=max(v[x],max(mx[son[x][0]],mx[son[x][1]]));
}
inline void toch1(int x,int y){
	if(!x){
		return ;
	}
	v1[x]=max(v1[x],y);
	ch1[x]=max(ch1[x],y);
}
inline void toch2(int x,int y){
	if(!x){
		return ;
	}
	v2[x]=max(v2[x],y);
	ch2[x]=max(ch2[x],y);
}
inline void pd(int x){
	if(ch1[x]){
		toch1(son[x][0],ch1[x]);
		toch1(son[x][1],ch1[x]);
		ch1[x]=0;
	}
	if(ch2[x]){
		toch2(son[x][0],ch2[x]);
		toch2(son[x][1],ch2[x]);
		ch2[x]=0;
	}
}
inline void cot(int x,int y,bool z){
	if(x){
		fa[x]=y;
	}
	if(y){
		son[y][z]=x;
	}
}
inline void rot(int x,bool z){
	int xx=fa[x],xxx=fa[xx];
	cot(son[x][z],xx,z^1);
	cot(x,xxx,son[xxx][1]==xx);
	cot(xx,x,z);
	ud(xx);
}
inline void apd(int x){
	int i;
	for(i=x;i;i=fa[i]){
		st[++tp]=i;
	}
	for(;tp;tp--){
		pd(st[tp]);
	}
}
void splay(int x,int y,int I){
	apd(x);
	int xx=fa[x],xxx=fa[xx];
	while(xx!=y){
		if(xxx==y){
			rot(x,son[xx][0]==x);
		}else{
			bool z=son[xxx][0]==xx;
			if(son[xx][z]==x){
				rot(x,z^1);
				rot(x,z);
			}else{
				rot(xx,z);
				rot(x,z);
			}
		}
		xx=fa[x],xxx=fa[xx];
	}
	ud(x);
	if(!y){
		rt[I]=x;
	}
}
void del(int x){
	splay(x,0,bel[x]);
	if(!son[x][0]){
		rt[bel[x]]=son[x][1];
		fa[rt[bel[x]]]=0;
	}else{
		int t=son[x][0];
		while(son[t][1]){
			t=son[t][1];
		}
		splay(t,x,bel[x]);
		cot(son[x][1],t,1);
		fa[t]=0;
		rt[bel[x]]=t;
		ud(t);
	}
	son[x][0]=son[x][1]=0;
	ud(x);
}
void ins(int x,int y){
	bel[x]=y;
	toch1(rt[bel[x]],v[x]);
	toch2(rt[bel[x]],siz[rt[bel[x]]]);
	v1[x]=max(v1[x],mx[rt[bel[x]]]);
	v2[x]=max(v2[x],siz[rt[bel[x]]]);
	cot(rt[bel[x]],x,0);
	rt[bel[x]]=x;
	ud(x);
}
void mov(int x,int y){
	del(x);
	ins(x,y);
}
int main(){
	//freopen("data.txt","r",stdin);
	int i,a,x,y;
	scanf("%d",&n);
	for(i=1;i<=n;i++){
		scanf("%d%d%d",&v[i],&x,&y);
		if(!h[make_pair(x,y)]){
			h[make_pair(x,y)]=++tot;
		}
		ins(i,h[make_pair(x,y)]);
	}
	scanf("%d",&m);
	while(m--){
		scanf("%d%d%d",&a,&x,&y);
		if(!h[make_pair(x,y)]){
			h[make_pair(x,y)]=++tot;
		}
		mov(a,h[make_pair(x,y)]);
	}
	for(i=1;i<=n;i++){
		splay(i,0,bel[i]);
		printf("%lld\n",(ll)v1[i]*v2[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

*/


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值
>