BZOJ2827: 千山鸟飞绝

Posted tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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行,每行一个数,代表每只鸟的战斗力。
 
 

 

Sample Input

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

Sample Output

3
4
6
8
8

HINT

 

对于样例的解释:

首先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
 

我的代码能力已经喂狗了。
这道题我们只要维护一个这样的数据结构就好啦:
1.在集合中插入元素。
2.在集合中删除元素。
3.在集合中更新所有点的答案。
然后Treap或函数式线段树(内存有点卡)上来打标记就好啦。
然后,然后,然后,就调了半天(你们知道什么是半天吗?)
最后操作执行结束后要把所有标记down掉更新答案。
代码写得又丑又长。

技术分享
#include<cstdio>
#include<cctype>
#include<queue>
#include<cmath>
#include<cstring>
#include<algorithm>
#define rep(i,s,t) for(int i=s;i<=t;i++)
#define dwn(i,s,t) for(int i=s;i>=t;i--)
#define ren for(int i=first[x];i;i=next[i])
using namespace std;
const int BufferSize=1<<16;
char buffer[BufferSize],*head,*tail;
inline char Getchar() {
    if(head==tail) {
        int l=fread(buffer,1,BufferSize,stdin);
        tail=(head=buffer)+l;
    }
    return *head++;
}
inline int read() {
    int x=0,f=1;char c=Getchar();
    for(;!isdigit(c);c=Getchar()) if(c==-) f=-1;
    for(;isdigit(c);c=Getchar()) x=x*10+c-0;
    return x*f;
}
typedef long long ll;
const int maxn=30010;
const int maxm=300010;
const int HASH=233233;
const int inf=2147483647;
struct Hash_Map {
    int first[HASH],next[maxm],valx[maxm],valy[maxm],cnt;
    int find(int x,int y) {
        int p=(x%HASH+y%HASH)%HASH;if(p<0) p+=HASH;
        for(int i=first[p];i;i=next[i]) if(valx[i]==x&&valy[i]==y) return i;
        valx[++cnt]=x;valy[cnt]=y;next[cnt]=first[p];
        return first[p]=cnt;
    }
}M;
int n,val[maxn],pos[maxn],ans1[maxn],ans2[maxn];
void update(int x,int v1,int v2) {
    ans1[x]=max(ans1[x],v1);
    ans2[x]=max(ans2[x],v2);
}
struct Node {
    Node* ch[2];
    int r,x,maxv,maxs;
    int s,mx;
    void relax(int v1,int v2) {
        maxs=max(maxs,v1);
        maxv=max(maxv,v2);
        update(x,maxs,maxv);
    }
    void pushdown() {
        if(ch[0]->maxs!=inf) ch[0]->relax(maxs,maxv);
        if(ch[1]->maxs!=inf) ch[1]->relax(maxs,maxv);
        update(x,maxs,maxv);
        maxv=maxs=0;
    }
    void maintain() {
        s=ch[0]->s+ch[1]->s+1;
        mx=max(val[x],max(ch[0]->mx,ch[1]->mx));
    }
}nodes[maxn],*null=&nodes[0];
queue<Node*> Q;
Node* newnode(int v) {
    Node* o=Q.front();Q.pop();
    o->maxv=o->maxs=0;
    o->ch[0]=o->ch[1]=null;
    o->r=rand();o->x=v;o->s=1;o->mx=val[v];
    return o;
}
void del(Node* &o) {Q.push(o);o=null;}
void rotate(Node* &o,int d) {
    Node* k=o->ch[d^1];o->pushdown();k->pushdown();
    o->ch[d^1]=k->ch[d];k->ch[d]=o;
    o->maintain();k->maintain();o=k;
}
void insert(Node* &o,int v) {
    if(o==null) o=newnode(v);
    else {
        o->pushdown();
        int d=v>o->x;insert(o->ch[d],v);
        if(o->ch[d]->r>o->r) rotate(o,d^1);
    }
    o->maintain();
}
void remove(Node* &o,int v) {
    o->pushdown();
    if(o->x==v) {
        Node *k=o;
        if(o->ch[0]==null) o=o->ch[1],del(k);
        else if(o->ch[1]==null) o=o->ch[0],del(k);
        else {
            int d=o->ch[0]->r>o->ch[1]->r;
            rotate(o,d);remove(o->ch[d],v);
        }
    }
    else remove(o->ch[v>o->x],v);
    if(o!=null) o->maintain();
}
void force(Node* &o) {
    if(o==null) return;
    o->pushdown();
    force(o->ch[0]);
    force(o->ch[1]);
}
Node* root[maxm];
int main() {
    null->maxs=null->maxv=inf;
    null->s=0;null->mx=-inf;
    rep(i,1,maxn-1) Q.push(&nodes[i]);
    rep(i,0,maxm-1) root[i]=null;
    n=read();
    rep(i,1,n) {
        val[i]=read();int x=read(),y=read(),T=M.find(x,y);
        if(root[T]!=null) {
            update(i,0,root[T]->mx);
            root[T]->relax(0,val[i]);
        }
        insert(root[pos[i]=T],i);
        root[T]->relax(root[T]->s-1,0);
    }
    dwn(i,read(),1) {
        int c=read(),x=read(),y=read(),T=M.find(x,y);
        if(T==pos[c]) continue;
        remove(root[pos[c]],c);
        if(root[T]!=null) {
            update(c,0,root[T]->mx);
            root[T]->relax(0,val[c]);
        }
        insert(root[pos[c]=T],c);
        root[T]->relax(root[T]->s-1,0);
    }
    rep(i,1,M.cnt) force(root[i]);
    rep(i,1,n) printf("%lld\n",(ll)ans2[i]*ans1[i]);
    return 0;
}
View Code

 

以上是关于BZOJ2827: 千山鸟飞绝的主要内容,如果未能解决你的问题,请参考以下文章

bzoj2827: 千山鸟飞绝

BZOJ2827 - 千山鸟飞绝

2827: 千山鸟飞绝 非旋treap

千山鸟飞绝

程序员段子:电脑在手,代码我有!

清平愿