BZOJ2827 - 千山鸟飞绝
Description
有\(n(n\leq10^5)\)只鸟分布在二维平面的整点上。每只鸟有威武值、士气值和团结值:威武值是固定的;士气值等于与其在同一位置的其他鸟的威武值的最大值;团结值等于与其在同一位置的其他鸟的只数。接下来\(t(t\leq2.5\times10^5)\)秒,第\(i\)秒会有一只鸟\(b_i\)由原位置飞向\((x_i,y_i)\)。求每只鸟在这\(t\)秒中,最大士气值与最大团结值的乘积。
Solution
用平衡树搞。
对于每个整点维护一棵splay,因为最多出现\(n+t\)个不同的坐标所以可以将每个坐标对应成一个数值,map
或者离散化均可。splay维护子树大小\(siz\),子树最大武力值\(maxV\),每个点的目前最大士气值\(ans_1\)和最大团结值\(ans_2\)。第\(i\)秒时按以下顺序进行操作:
- 将\(b_i\)从原树中删除。\(b_i\)的离开不会使原位置上的鸟的答案变优,所以不用管它们的\(ans\)。
- 将\((x_i,y_i)\)对应的splay中所有点的\(ans_1\)与\(i\)的武力值取max,\(ans_2\)与该树的大小取max。可以打标记。
- 将\(b_i\)的\(ans_1\)与\((x_i,y_i)\)对应的splay的\(maxV\)取max,\(asn_2\)与该树的大小取max。
- 将\(b_i\)插入该树中。直接将\(b_i\)设置为该树的根的父亲就好,因为我们的splay不需要按什么关键字来维护。
\(t\)秒后,将所有标记下放,输出\(ans_1[i]\times ans_2[i]\)。
时间复杂度\(O(tlogn)\)。
Code
//千山鸟飞绝
#include <cstdio>
#include <map>
#include <queue>
using namespace std;
typedef pair<int,int> pairI;
inline char gc()
{
static char now[1<<16],*S,*T;
if(S==T) {T=(S=now)+fread(now,1,1<<16,stdin); if(S==T) return EOF;}
return *S++;
}
inline int read()
{
int x=0,f=1; char ch=gc();
while(ch<'0'||'9'<ch) f=ch^'-'?f:-1,ch=gc();
while('0'<=ch&&ch<='9') x=x*10+ch-'0',ch=gc();
return x*f;
}
int const N=1e5+10;
int n; pairI pos[N];
int cnt; map<pairI,int> h;
int rt[N<<2],fa[N],ch[N][2],siz[N];
int maxV[N],val[N],ans1[N],ans2[N];
int tag1[N],tag2[N];
int wh(int p) {return p==ch[fa[p]][1];}
void clear(int p) {fa[p]=ch[p][0]=ch[p][1]=0,siz[p]=1; maxV[p]=val[p]; tag1[p]=tag2[p]=0;}
void update(int p)
{
int ch0=ch[p][0],ch1=ch[p][1];
siz[p]=siz[ch0]+1+siz[ch1];
maxV[p]=max(val[p],max(maxV[ch0],maxV[ch1]));
}
void mark(int p,int t1,int t2)
{
tag1[p]=max(tag1[p],t1),ans1[p]=max(ans1[p],tag1[p]);
tag2[p]=max(tag2[p],t2),ans2[p]=max(ans2[p],tag2[p]);
}
void pushdw(int p)
{
int ch0=ch[p][0],ch1=ch[p][1];
if(tag1[p]) mark(ch0,tag1[p],0),mark(ch1,tag1[p],0),tag1[p]=0;
if(tag2[p]) mark(ch0,0,tag2[p]),mark(ch1,0,tag2[p]),tag2[p]=0;
}
void rotate(int p)
{
int q=fa[p],r=fa[q],w=wh(p);
fa[p]=r; if(r) ch[r][wh(q)]=p;
fa[ch[q][w]=ch[p][w^1]]=q;
fa[ch[p][w^1]=q]=p;
update(q),update(p);
}
void pushdwRt(int p) {if(fa[p]) pushdwRt(fa[p]); pushdw(p);}
void splay(int p)
{
pushdwRt(p);
for(int q=fa[p];q;rotate(p),q=fa[p]) if(fa[q]) rotate(wh(p)^wh(q)?p:q);
rt[h[pos[p]]]=p;
}
void ins(pairI c,int p)
{
pos[p]=c;
if(!h[c]) {h[c]=++cnt,rt[h[c]]=p; return;}
int q=rt[h[c]];
ans1[p]=max(ans1[p],maxV[q]);
ans2[p]=max(ans2[p],siz[q]);
mark(q,val[p],siz[q]);
fa[ch[p][0]=q]=p,update(rt[h[c]]=p);
}
void del(int p)
{
pairI c=pos[p];
splay(p);
if(!ch[p][0]) {rt[h[c]]=ch[p][1],fa[rt[h[c]]]=0; return;}
int q=ch[p][0]; while(ch[q][1]) q=ch[q][1];
splay(q); fa[ch[q][1]=ch[p][1]]=q; update(q);
}
void pushdwAll(int p)
{
if(!p) return;
pushdw(p); pushdwAll(ch[p][0]),pushdwAll(ch[p][1]);
}
int main()
{
n=read();
for(int i=1;i<=n;i++)
{
siz[i]=1; maxV[i]=val[i]=read();
int x=read(),y=read(); ins(pairI(x,y),i);
}
int t=read();
for(int i=1;i<=t;i++)
{
int p=read(),x=read(),y=read();
del(p); clear(p);
ins(pairI(x,y),p);
}
for(int i=1;i<=cnt;i++) pushdwAll(rt[i]);
for(int i=1;i<=n;i++) printf("%lld\n",(long long)ans1[i]*ans2[i]);
return 0;
}