目录
题目
解题思路
首先,此题有明显的插入、删除、查找,所以必须要使用平衡树。
考虑如何使用平衡树维护每个鸟的状态。发现很不方便,因为鸟的位置改变,整个平衡树的值都要修改。
考虑针对每个节点开一颗平衡树,这样就有\(3e4\times 3e4\)棵树。这显然太多了,考虑离散化。
可以使用\(map\)存储。
细节很多,但是有很多收获:val[]
在相同时可以直接插入。
code
#include<iostream>
#include<cstdio>
#include<map>
using namespace std ;
#define pii pair<int,int>
const int MAXN = 3e5+10 ;
int siz[MAXN] ,ch[MAXN][2] ,val[MAXN] ,w[MAXN] ,q[MAXN] ,a[MAXN] ;
int fa[MAXN] ,rt[MAXN] ,tot = 0 ;
int slazy[MAXN] ,wlazy[MAXN] ,ans1[MAXN] ,ans2[MAXN] ;
inline void maintain(int x){
siz[x] = siz[ch[x][0]] + siz[ch[x][1]] + 1 ;
val[x] = max(max(val[ch[x][0]] , val[ch[x][1]]) , w[x]) ;
}
inline bool islrch(int x){
return ch[fa[x]][1] == x ;
}
inline void clear(int x){
siz[x] = ch[x][1] = ch[x][0] = val[x] = fa[x] = slazy[x] = wlazy[x] = 0 ;
}
inline void rotate(int x){
int y = fa[x] ,z = fa[y] ;
int chk = islrch(x) ;
ch[y][chk] = ch[x][chk ^ 1] ;
fa[ch[x][chk ^ 1]] = y ;
ch[x][chk ^ 1] = y ;
fa[y] = x ;
fa[x] = z ;
if(z) ch[z][ch[z][1] == y] = x ;
maintain(y) ;
maintain(x) ;
}
inline void pushdown(int x){
int k1 = wlazy[x] ,k2 = slazy[x] ;
for(int i = 0;i < 2;++i)
if(ch[x][i]){
int c = ch[x][i] ;
ans1[c] = max(ans1[c] , k1) ;
ans2[c] = max(ans2[c] , k2) ;
wlazy[c] = max(k1 , wlazy[c]) ;
slazy[c] = max(k2 , slazy[c]) ;
}
slazy[x] = wlazy[x] = 0 ;
}
int stack[MAXN] ,topp = 0 ;
inline int splay(int x){
for(int i = x;i;i = fa[i]) stack[++topp] = i ;
while(topp) pushdown(stack[topp--]) ;
for(int f = fa[x];f = fa[x] ,f;rotate(x))
if(fa[f]) rotate(islrch(f) == islrch(x) ? f : x) ;
return x ;
}
inline int pre(int x){
int cur = ch[rt[x]][0] ;
while(ch[cur][1]) cur = ch[cur][1] ;
rt[x] = splay(cur) ;
return cur ;
}
inline void del(int r , int x){
rt[r] = splay(x) ;
if(!ch[rt[r]][0] && !ch[rt[r]][1]){
clear(rt[r]) ;
rt[r] = 0 ;
return ;
}
if(!ch[rt[r]][0]){
int cur = rt[r] ;
rt[r] = ch[rt[r]][1] ;
fa[rt[r]] = 0 ;
clear(cur) ;
return ;
}
if(!ch[rt[r]][1]){
int cur = rt[r] ;
rt[r] = ch[rt[r]][0] ;
fa[rt[r]] = 0 ;
clear(cur) ;
return ;
}
int cur = rt[r] ,f = pre(r) ;
fa[ch[cur][1]] = f ;
ch[f][1] = ch[cur][1] ;
clear(cur) ;
maintain(rt[r]) ;
}
inline void ins(int &r , int x , int f){//插入节点
if(!r){
r = x ;
fa[r] = f ;
val[r] = w[r] ;
siz[r] = 1 ;
return ;
}
pushdown(r) ;
if(!ch[r][0]) ins(ch[r][0] , x , r) ;//此题中的val表示为最大值,同一棵树的val相同。
else ins(ch[r][1] , x , r) ;
}
map<pii , int> vis ;
int num ;
int main(){
int n ;scanf("%d" , &n) ;
for(int i = 1;i <= n;++i){
int x ,y ;scanf("%d%d%d" , w+i , &x , &y) ;
if(!vis.count(make_pair(x , y))) vis[make_pair(x , y)] = ++num ;
int k = vis[make_pair(x , y)] ;
a[i] = k ;
ans1[i] = max(ans1[i] , val[rt[k]]) ;
ans2[i] = max(ans2[i] , siz[rt[k]]) ;
ins(rt[k] , i , 0) ;
rt[k] = splay(i) ;
wlazy[rt[k]] = max(wlazy[rt[k]] , w[i]) ;
slazy[rt[k]] = max(slazy[rt[k]] , siz[rt[k]]-1) ;
}
int t ;scanf("%d" , &t) ;
while(t--){
int id ,x ,y ;
scanf("%d%d%d" , &id , &x , &y) ;
if(!vis.count(make_pair(x , y))){
vis[make_pair(x , y)] = ++num ;
}
int k = vis[make_pair(x , y)] ,pre = a[id] ;
a[id] = k ;
del(pre , id) ;
ans1[id] = max(ans1[id] , val[rt[k]]) ;
ans2[id] = max(ans2[id] , siz[rt[k]]) ;
ins(rt[k] , id , 0) ;
rt[k] = splay(id) ;
wlazy[rt[k]] = max(wlazy[rt[k]] , w[id]) ;
slazy[rt[k]] = max(slazy[rt[k]] , siz[rt[k]]-1) ;
}
for(int i = 1;i <= n;++i){
rt[a[i]] = splay(i) ;
printf("%lld\n" , 1ll * ans1[i] * ans2[i]) ;
}
return 0 ;
}
标签:rt,ch,cur,int,luogu,fa,MAXN,题解,山鸟飞
From: https://www.cnblogs.com/adolf-stalin/p/17615723.html