bzoj 2827 千山鸟飞绝 平衡树

原创 2017年01月04日 08:10:06

splay和我的常数加到一起简直是灾难。。。
坐标没有用,把它离散掉。
然后splay维护一个最大值和次大值和最大size的标记。
插入的时候查询一下,打个标记。

#include <bits/stdc++.h>
using namespace std;
#define N 410000
#define M 810000
#define ll long long
#define ls(x) ch[x][0]
#define rs(x) ch[x][1]
#define which(x) (ch[fa[x]][1]==x)
#define icmp(x,y) (x^y ? v[x]^v[y] ? v[x]>v[y] ? 1:-1 : x>y ? 1:-1 :0)
const int inf=~0U>>1;
int n,m,cnt,tot;
int v[M],a[N],av[M],as[M],rem[N],root[N];
int size[M],L[N],R[N],l,r;
ll val[N],pos[N],org[N];
int ch[M][2],fa[M],mx[M],sx[M],sum[M];
char getc()
{
    static const int LEN = 4096;
    static char buf[LEN],*S=buf,*T=buf;
    if(S == T)
    {
        T = (S=buf)+fread(buf,1,LEN,stdin);
        if(S == T)return EOF;
    }
    return *S++;
}
int read()
{
    static char ch;
    static int D;
    while(!isdigit(ch=getc()));
    for(D=ch-'0'; isdigit(ch=getc());)
        D=(D<<3)+(D<<1)+(ch-'0');
    return D;
}
void upd(int x)
{
    as[x]=max(as[x],sum[x]);
    int t=mx[x]==x ? sx[x]:mx[x];
    if(v[t]>v[av[x]])av[x]=t;
}
void cal(int x,int y)
{
    if(!x||!y||mx[x]==y||sx[x]==y)return;
    if(v[y]>v[mx[x]])sx[x]=mx[x],mx[x]=y;
    else if(v[y]>v[sx[x]])sx[x]=y;
}
void pushdown(int x)
{
    if(sum[x])
    {
        sum[ls(x)]=max(sum[ls(x)],sum[x]);
        sum[rs(x)]=max(sum[rs(x)],sum[x]);
    }
    cal(ls(x),mx[x]);cal(rs(x),mx[x]);
    cal(ls(x),sx[x]);cal(rs(x),sx[x]);
    upd(ls(x));upd(rs(x));
    mx[x]=sx[x]=0;sum[x]=0;
}
void pushup(int x)
{size[x]=size[ls(x)]+size[rs(x)]+1;}
void down(int x)
{
    if(fa[x])down(fa[x]);
    pushdown(x);
}
void rotate(int x)
{
    int y=fa[x],k=which(x);
    ch[y][k]=ch[x][k^1];
    ch[x][k^1]=y;
    ch[fa[y]][which(y)]=x;
    fa[x]=fa[y];fa[y]=x;
    fa[ch[y][k]]=y;

    pushup(y);pushup(x);
}
void splay(int x,int tar)
{
    down(x);
    while(fa[x]!=tar)
    {
        int y=fa[x];
        if(fa[y]==tar)rotate(x);
        else
        {
            if(which(x)^which(y))rotate(x);
            else rotate(y);
            rotate(x);
        }
    }
}
void pre(int x,int y)
{
    if(!x)return;
    if(icmp(x,y)<0)
    {
        if(icmp(x,l)>0)l=x;
        pre(ch[x][1],y);
    }
    else pre(ch[x][0],y);
}
void nex(int x,int y)
{
    if(!x)return;
    if(icmp(x,y)>0)
    {
        if(icmp(x,r)<0)r=x;
        nex(ch[x][0],y);
    }
    else nex(ch[x][1],y);
}
int find(int x,int K)
{
    int t=size[ch[x][0]];
    if(t+1==K)return x;
    if(t>=K)return find(ch[x][0],K);
    return find(ch[x][1],K-t-1);
}
void build(int x,int y,int pos)
{
    root[pos]=x;
    L[pos]=x;R[pos]=y;
    ch[x][1]=y;v[x]=-1;v[y]=inf;
    fa[y]=x;size[x]=2;size[y]=1;
}
void del(int pos,int x)
{
    int &rt=root[pos];
    l=L[pos];r=R[pos];
    pre(rt,x);nex(rt,x);
    splay(l,0);rt=l;splay(r,l);
    size[l]--;size[r]--;
    ch[r][0]=fa[x]=0;
}
void ins(int pos,int x)
{
    int &rt=root[pos];
    if(size[rt]>2)
    {
        int t=find(rt,size[rt]-1);
        if(icmp(t,av[x])>0)av[x]=t;
    }
    l=L[pos];r=R[pos];
    pre(rt,x);nex(rt,x);
    splay(l,0);rt=l;splay(r,l);
    size[l]++;size[r]++;
    ch[r][0]=x;fa[x]=r;size[x]=1;
    cal(rt,x);sum[rt]=max(sum[rt],size[rt]-3);
    upd(rt);
}
int main()
{
    n=read();
    for(int i=1,x,y;i<=n;i++)
    {
        v[i]=read();x=read();y=read();
        org[i]=val[++cnt]=(ll)x*inf+y;
    }
    m=read();
    for(int i=1,x,y;i<=m;i++)
    {
        a[i]=read();x=read();y=read();
        pos[i]=val[++cnt]=(ll)x*inf+y;
    }
    sort(val+1,val+1+cnt);
    cnt=unique(val+1,val+1+cnt)-val-1;
    tot=n;
    for(int i=1;i<=cnt;i++)
        build(tot+1,tot+2,i),tot+=2;
    for(int i=1;i<=n;i++)
    {
        org[i]=lower_bound(val+1,val+1+cnt,org[i])-val;
        ins(org[i],i);
    }
    for(int i=1,t;i<=m;i++)
    {
        t=a[i];del(org[t],t);
        pos[i]=lower_bound(val+1,val+1+cnt,pos[i])-val;
        org[t]=pos[i];ins(org[t],t);
    }
    for(int i=1;i<=n;i++)
    {
        down(i);
        printf("%lld\n",(ll)v[av[i]]*as[i]);
    }
    return 0;
}
版权声明:本文为博主原创文章,未经博主允许不得转载。

BZOJ2827 千山鸟飞绝

这个……我们会发现,坐标其实没毛卵用,只不过是区分不同的点 所以我们直接把坐标离散化了 然后鸟来回飞就相当于一个维护集合大小,集合max,一个集合里的某个权值对一个数取max 拿个splay随便...
  • neither_nor
  • neither_nor
  • 2016年08月19日 19:23
  • 603

BZOJ 2827 千山鸟飞绝 Treap

题目大意:自己看 首先我们可以写个哈希表来存坐标 当我们改变一个点的坐标时,被加入的集合中的点和这个点之间会产生相互的影响。。。 我们首先考虑集合中的点对这个点的影响 显然ans1是集合中的最...
  • PoPoQQQ
  • PoPoQQQ
  • 2015年03月17日 22:06
  • 2173

bzoj 2827 千山鸟飞绝 平衡树

splay和我的常数加到一起简直是灾难。。。 坐标没有用,把它离散掉。 然后splay维护一个最大值和次大值和最大size的标记。 插入的时候查询一下,打个标记。#include using ...
  • make_it_for_good
  • make_it_for_good
  • 2017年01月04日 08:10
  • 432

bzoj 4180: 字符串计数 (后缀自动机+矩阵乘法)

4180: 字符串计数 Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 140  Solved: 63 [Submit][Status][Dis...
  • clover_hxy
  • clover_hxy
  • 2017年03月04日 16:39
  • 275

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

题解: 首先先把坐标离散化一下, 然后对于每个坐标点我们建一棵平衡树,每次插入操作后给整颗平衡树下传一下需求的两个标记。 注意: splay有的人(比如我)习惯每棵都先建-inf、inf两...
  • Vmurder
  • Vmurder
  • 2015年05月14日 15:17
  • 1658

bzoj 2827 千山鸟飞绝(treap)

treap
  • u013849646
  • u013849646
  • 2016年04月04日 12:41
  • 241

[bzoj2827]千山鸟飞绝【splay】

[题目描述] 2827: 千山鸟飞绝 Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 815  Solved: 231 [Submit...
  • D_Vanisher
  • D_Vanisher
  • 2018年01月18日 10:34
  • 28

bzoj 2827: 千山鸟飞绝

题意:乱七八糟。题解:坐标没卵用,直接map掉就好。 然后对每一个位置开一个splay,直接删点,加点。标记一下。 最后输出的时候都splay下就好了。 细节略多需小心。 code:#incl...
  • qq_36808030
  • qq_36808030
  • 2017年09月18日 16:56
  • 232

bzoj2827千山鸟飞绝(Treap)

题目描述 话说有一天doyouloveme和vfleaking到山里玩。谁知doyouloveme刚刚进山,所有的鸟儿竟被他的神犇气场给惊得全部飞走了。vfleaking顿时膜拜不已。 这时鸟王用鸟...
  • H_Anonymity
  • H_Anonymity
  • 2017年09月26日 16:39
  • 96

2827: 千山鸟飞绝 splay打标记

Description 话说有一天doyouloveme和vfleaking到山里玩。谁知doyouloveme刚刚进山,所有的鸟儿竟被他的神犇气场给惊得全部飞走了。vfleaking顿时膜...
  • baidu_36797646
  • baidu_36797646
  • 2018年02月14日 10:36
  • 49
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:bzoj 2827 千山鸟飞绝 平衡树
举报原因:
原因补充:

(最多只允许输入30个字)