bzoj2827: 千山鸟飞绝

Description

话说有一天doyouloveme和vfleaking到山里玩。谁知doyouloveme刚刚进山,所有的鸟儿竟被他的神犇气场给惊得全部飞走了。vfleaking顿时膜拜不已。

这时鸟王用鸟语说道:“[email protected]#$%……?”安抚了一下众鸟的情绪。鸟王生性好斗,作出了一个决定——要排鸟布阵把刚才吓到它们的人类赶出山去。

每只鸟都有一个编号,都有一个威武值。每秒钟鸟王都会发一个命令,编号为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行,每行一个数,代表每只鸟的战斗力。

对每只鸟建一个节点,每个坐标维护一颗平衡树,同时维护标记(区间最/次大值,size,全树最/次大值,size,单点历史最/次大值,历史最大size等),每个操作对应平衡树的插入和删除,处理完所有询问最后暴力下传所有标记即得到答案

#include<cstdio>
#include<cstdlib>
int _(){
    int x=0,c=getchar(),f=1;
    while(c<48)c==‘-‘&&(f=-1),c=getchar();
    while(c>47)x=x*10+c-48,c=getchar();
    return x*f;
}
const int P=621239;
int h[P][4];
int&get(int x,int y){
    int w=unsigned(x*1844677+y*293+141)%P;
    while(h[w][2]){
        if(h[w][0]==x&&h[w][1]==y)return h[w][3];
        if((w+=12347)>=P)w-=P;
    }
    h[w][0]=x;h[w][1]=y;h[w][2]=1;
    return h[w][3];
}
inline void maxs(int&a,int b){if(a<b)a=b;}
int n,q;
struct node{
    int rnd,v0,x,y,ch[2],m1,m2,m3,mt[3],as[3];
    void Ins();
    void Del();
    long long val(){
        return 1ll*(v0==as[0]?as[1]:as[0])*(as[2]-1);
    }
    void clr(){
        ch[0]=ch[1]=0;
        m1=v0;m2=0;m3=1;
        for(int i=0;i<3;++i)mt[i]=0;
    }
    void upd(){
        mt[0]=m1;mt[1]=m2;mt[2]=m3;
        for(int i=0;i<3;++i)maxs(as[i],mt[i]);
    }
}ns[30007];
inline void chk(int&a,int&b,int c){
    if(c>=a)b=a,a=c;
    else if(c>b)b=c;
}
inline void maxs(int&a,int&b,int c){
    if(a<c)a=c;
    if(b<c)b=c;
}
void dn(int w){
    for(int d=0,u;d<2;++d)if(u=ns[w].ch[d]){
        for(int j=0;j<3;++j)maxs(ns[u].mt[j],ns[u].as[j],ns[w].mt[j]);
    }
    for(int j=0;j<3;++j)ns[w].mt[j]=0;
}
void dns(int w){
    if(!w)return;
    dn(w);
    for(int d=0;d<2;++d)dns(ns[w].ch[d]);
}
void up(int w){
    ns[w].m1=ns[w].v0;ns[w].m2=0;ns[w].m3=1;
    for(int d=0,u;d<2;++d)if(u=ns[w].ch[d]){
        chk(ns[w].m1,ns[w].m2,ns[u].m1);
        chk(ns[w].m1,ns[w].m2,ns[u].m2);
        ns[w].m3+=ns[u].m3;
    }
}
void rot(int&w,int d){
    int u=ns[w].ch[d];
    dn(w);dn(u);
    ns[w].ch[d]=ns[u].ch[d^1];
    ns[u].ch[d^1]=w;
    up(w);up(u);
    w=u;
}
void ins(int&w,int x){
    if(!w){
        w=x;
        return;
    }
    dn(w);
    int d=w<x;
    ins(ns[w].ch[d],x);
    if(ns[ns[w].ch[d]].rnd>ns[w].rnd)rot(w,d);
    else up(w);
}
void dels(int&w){
    if(ns[w].ch[0]|ns[w].ch[1]){
        int d=ns[ns[w].ch[0]].rnd<ns[ns[w].ch[1]].rnd;
        rot(w,d);
        dels(ns[w].ch[d^1]);
        up(w);
    }else w=0;
}
void del(int&w,int x){
    if(w==x){
        dels(w);
        return;
    }
    dn(w);
    int d=w<x;
    del(ns[w].ch[d],x);
    if(ns[ns[w].ch[d]].rnd>ns[w].rnd)rot(w,d);
    else up(w);
}
void node::Ins(){
    clr();
    int&rt=get(x,y);
    ins(rt,this-ns);
    ns[rt].upd();
}
void node::Del(){
    int&rt=get(x,y);
    del(rt,this-ns);
    if(rt)ns[rt].upd();
    clr();
}
int main(){
    srand(29397);
    n=_();
    for(int i=1;i<=n;++i){
        ns[i].v0=_();
        ns[i].x=_();
        ns[i].y=_();
        ns[i].rnd=rand();
        ns[i].Ins();
    }
    for(q=_();q;--q){
        int i=_();
        ns[i].Del();
        ns[i].x=_();
        ns[i].y=_();
        ns[i].Ins();
    }
    for(int i=0;i<P;++i)dns(h[i][3]);
    for(int i=1;i<=n;++i)printf("%lld\n",ns[i].val());
    return 0;
}
时间: 2024-10-06 18:08:50

bzoj2827: 千山鸟飞绝的相关文章

bzoj2827: 千山鸟飞绝 treap

离散化坐标,每个坐标开一棵以鸟的编号为关键字的平衡树.每次插入时打2个标记,同时更新自身.这个方法比较显然,而且好写.正解好像用很迷的方法乱搞了一波,然后用线段树不打标记就做出来了,并不会. treap旋转没传引用,调了好久. #include<bits/stdc++.h> #define N 30005 #define M 330005 #define x first #define y second #define IF else if using namespace std; int n

【BZOJ2827】千山鸟飞绝 离散化+splay

链接: #include <stdio.h> int main() { puts("转载请注明出处[vmurder]谢谢"); puts("网址:blog.csdn.net/vmurder/article/details/45721413"); } 题解: 首先先把坐标离散化一下, 然后对于每个坐标点我们建一棵平衡树,每次插入操作后给整颗平衡树下传一下需求的两个标记. 注意: splay有的人(比如我)习惯每棵都先建-inf.inf两个节点以便于查找前驱

bzoj 2827: 千山鸟飞绝

2827: 千山鸟飞绝 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 802  Solved: 228[Submit][Status][Discuss] Description 话说有一天doyouloveme和vfleaking到山里玩.谁知doyouloveme刚刚进山,所有的鸟儿竟被他的神犇气场给惊得全部飞走了.vfleaking顿时膜拜不已. 这时鸟王用鸟语说道:“[email protected]#$%……?”安抚了一下众鸟的情绪.鸟王

千山鸟飞绝

1 #include <cmath> 2 #include <ctime> 3 #include <cstdio> 4 #include <cstdlib> 5 #include <cstring> 6 #include <iostream> 7 #include <algorithm> 8 # define maxn 30010 9 using namespace std; 10 void ot(int x){cout&

2827: 千山鸟飞绝 非旋treap

国际惯例的题面:看起来很不可做的样子,我们先来整理一下题意吧.就是,维护每个点曾经拥有过的最大的两个属性值,支持把点的位置移动.我们用map对每个位置进行离散化,对每个位置建立一个平衡树.为了方便分离,这个平衡树的关键字是节点编号.然后把每个点当做一个节点,放进其所在位置的平衡树里.剩下要做的就是平衡树分离出一个点,合并一个点,还有打标记了.对于士气值的标记,我们维护平衡树中的max,每次合并的时候,用这个新点的威武值去给整棵树打标记,再用树中的max给这个新点打标记.团结值的标记,合并后一起打

python/HTML基础

---恢复内容开始--- python/HTML基础 HTML: 超文本标记(标签)语言 (以<>扩起来的都是标签语言,放入标签里的不仅仅是文本)一套语言规则 浏览器的渲染顺序是从上到下,从左到右 不同的浏览器,对同一标签可能会有不完全相同的解释(兼容性)至今已经解决的差不多了 .html或htm   静态网页文件扩展名后缀 标签可以进行嵌套,但是不能进行交叉嵌套 HTML 不是一种编程语言,而是一种标记语言,HTML使用标记标签来描述网页 HTML结构: <html></h

冬天的雪

时光,从一缕清风中飘然而过,散发出幽幽的暗香,在四季轮回的罅隙中,缓缓地步入了冬季.冬,蕴含着深邃悠远的意韵:雪,舞动着空灵曼妙的风姿.静静聆听雪花飘落的声音,感受那份宁静幽美的意境. 让我们从古人的诗情画意中,去细细品味雪带给人们的那种空寂悠远的意境吧. "千山鸟飞绝,万径人踪灭,孤舟蓑笠翁,独钓寒江雪."柳宗元的一首<江雪>,描绘了一幅动人的画面.在白雪覆盖的江面上,一叶小舟,一个披蓑戴笠的老渔翁,独自在寒冷的江心垂钓.天地间空旷寂静,彰显了渔翁的清高与孤傲. 张岱的&

C# Tcp协议收发数据(TCPClient发,Socket收)

运行这个程序前需要先关闭Windows防火墙,Win7系统关闭防火墙的方法是在控制面板的"控制面板\系统和安全\Windows 防火墙\自定义设置"路径中,将"家庭或工作(专用)网络位置设置"和"公用网络位置设置"下面的选项都选到"关闭Windows防火墙(不推荐)". 1.界面设计 左侧为发送数据的输入框,单击"发送数据"把数据发送到指定IP地址的指定端口号.(本例中,IP地址和端口号都被写死到代码中)

怎样有效提高记忆力?

周筠 ,虚晃一枪. 陈甫鸼等 747 人赞同 我是坚定的“最浅的墨水胜过最深的记忆”党人.这辈子永不退党,哈哈. 读书记不住,可能原因有两点. 一,那是你不得不读的书:二,你没有随手做点笔记的习惯. 拿我自己来讲,如果是我想读的书,我才不会正襟危坐从头读起,我会快速翻页,找自己感兴趣的章节.关键词.图片,从最有兴趣的地方读起.比如,最近两天出差,读完了陈平原的书从文人之文到学者之文 (豆瓣) .300多页的书,一阵乱翻后,从顾炎武开始看,然后又跳到前面看张岱,接着又跑到后面看黄宗羲,继而跑到前面