bzoj2827千山鸟飞绝(Treap)

来源:互联网 发布:查看淘宝买家退货率 编辑:程序博客网 时间:2024/05/18 12:30

题目描述

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

输入

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

输出

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

样例输入

51 1 13 1 24 4 42 0 12 2 351 1 22 4 42 4 33 0 15 0 1

样例输出

34688

提示

对于样例的解释:
首先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的非负整数。

首先我们可以注意到坐标没啥用,离散一下;然后我们在每个坐标上开一个Treap打标记维护这个点上的信息(size和最大val)然后每个鸟路过时,更新答案即可.注意标记在旋转和删除时都要pushdown.
#include <cstdio>#include <iostream>#include <algorithm>#include <cstdlib>#include <map>#define maxn 30005#define maxm 300005using namespace std;inline int read(){   char c=getchar();int x=0,y=1;while(c<'0'||c>'9'){if(c=='-') y=-1;c=getchar();}while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();return x*y;}template<typename T>inline T m_max(T x,T y){return x>y?x:y;}int n,m,cnt,W[maxn],ans[maxn],ans2[maxn],las[maxn];struct node{int x,y;node(int a=0,int b=0):x(a),y(b){}friend bool operator <(const node a,const node b){return a.x==b.x?a.y<b.y:a.x<b.x;}};map<node,int>mp;struct Treap{Treap *ch[2];int v,s,r,ma,ms;Treap(int x=0):v(x),s(1),ma(0),ms(0),r(rand()){ch[0]=ch[1]=NULL;}inline int sz(){return this?this->s:0;}inline void reval(int x,int y){if(!this) return;this->ma=m_max(this->ma,x);this->ms=m_max(this->ms,y);ans[this->v]=m_max(ans[this->v],x);ans2[this->v]=m_max(ans2[this->v],y);}inline void mt(){if(!this) return; this->s=this->ch[0]->sz()+this->ch[1]->sz()+1;}inline void dn(){if(!this) return;if(!this->ma&&!this->ms) return;this->ch[0]->reval(this->ma,this->ms);this->ch[1]->reval(this->ma,this->ms);this->ma=this->ms=0;}inline void rotate(Treap*& now,int d){Treap* k=now->ch[d^1];now->dn();k->dn();now->ch[d^1]=k->ch[d];k->ch[d]=now;now->mt();k->mt();now=k;}inline void insert(Treap*& now,int x){if(!now){now=new Treap(x);return;}now->dn();int d;if(W[x]<W[now->v]||(W[x]==W[now->v]&&x<now->v)) d=0;else d=1;insert(now->ch[d],x);if(now->ch[d]->r < now->r) rotate(now,d^1);now->mt();}inline void del(Treap*& now,int x){now->dn();if(W[now->v]==W[x]&&now->v==x){if(now->ch[0]&&now->ch[1]){int d=now->ch[0]->r < now->ch[1]->r;rotate(now,d);del(now->ch[d],x);}else{Treap* tmp=now;now=now->ch[0]?now->ch[0]:now->ch[1];delete tmp;//不能析构...}}else{if(W[now->v]>W[x]||(W[now->v]==W[x]&&now->v>x)) del(now->ch[0],x);else del(now->ch[1],x);}if(now) now->mt();}inline int gmax(Treap* now){if(!now->ch[1]) return W[now->v];return gmax(now->ch[1]);}}*root[maxn+maxm];int main(){n=read();node tmp;int x,y,z;for(int i=1;i<=n;++i){W[i]=read();x=read();y=read();tmp=node(x,y);if(!mp.count(tmp)) mp[tmp]=++cnt;int now=mp[tmp];las[i]=now;if(root[now]) ans[i]=m_max(ans[i],root[now]->gmax(root[now])),root[now]->reval(W[i],0);root[now]->insert(root[now],i);root[now]->reval(0,root[now]->sz()-1);}m=read();for(int i=1;i<=m;++i){x=read();y=read();z=read();tmp=node(y,z);if(!mp.count(tmp)) mp[tmp]=++cnt;int now=mp[tmp];root[las[x]]->del(root[las[x]],x);las[x]=now;if(root[now]) ans[x]=m_max(ans[x],root[now]->gmax(root[now])),root[now]->reval(W[x],0);root[now]->insert(root[now],x);root[now]->reval(0,root[now]->sz()-1);}for(int i=1;i<=n;++i) root[las[i]]->del(root[las[i]],i);for(int i=1;i<=n;++i) printf("%lld\n",(long long)ans[i]*ans2[i]);return 0;}




原创粉丝点击