关闭

【BZOJ2151】种树,贪心+Splay乱搞

123人阅读 评论(0) 收藏 举报

Time:2016.08.29
Author:xiaoyimi
转载注明出处谢谢


传送门
模拟题之一
我真不知道怎么证明的
考试的时候纯粹是胡思乱想啊啊啊
具体做法就是把这n个数摆成一个环,记录每个数i左边和右边(前驱和后继)记作L[i],R[i]
每次取出一个最大的数data[x]记到答案中,把x重新赋值为data[x]-data[L[x]]-data[R[x]],删去x的前驱和后继L[x],R[x],然后更新x的前驱和后继
当时YY,感觉和最大权闭合子图有些类似
什么残流思想……不是很懂
完整的证明: orz大神
这样的话我们需要一个能够维护插入,删除,求最大值的数据结构
是什么呢?
GTMD堆
太弱只会Splay,不喜欢手打堆,因为在noip2015上手写堆给我留下了阴影……
代码:

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#define M 200003
using namespace std;
int n,m,root;
int L[M],R[M];
struct Splay{
    int fa,ch[2],siz,data;
}a[M]; 
void ct(int x){a[x].siz=a[a[x].ch[0]].siz+a[a[x].ch[1]].siz+1;}
void made(int id,int x){a[id].data=x;a[id].siz=1;a[id].fa=0;a[id].ch[0]=a[id].ch[1]=0;}
void rorate(int x,bool mk)
{
    int y=a[x].fa;
    a[y].ch[!mk]=a[x].ch[mk];
    a[a[x].ch[mk]].fa=y;
    if (a[y].fa)
    {
        if (a[a[y].fa].ch[0]==y) a[a[y].fa].ch[0]=x;
        else a[a[y].fa].ch[1]=x;
    }
    a[x].fa=a[y].fa;
    a[y].fa=x;
    a[x].ch[mk]=y;
    ct(y);ct(x);
}
void splay(int x,int goal)
{
    int y;
    while (a[x].fa!=goal)
    {
        y=a[x].fa;
        if (a[y].fa==goal)
        {
            if(a[y].ch[0]==x) rorate(x,1);
            else rorate(x,0);
        }
        else if (a[a[y].fa].ch[0]==y)
        {
            if (a[y].ch[0]==x) rorate(y,1);
            else rorate(x,0);
            rorate(x,1);
        }
        else
        {
            if (a[y].ch[1]==x) rorate(y,0);
            else rorate(x,1);
            rorate(x,0);
        }
    }
    if(!goal) root=x;
}
void insert(int id,int x)
{
    made(id,x);
    if (!root) {root=id;return;}
    int now=root,f=1;
    while (f)
    {
        a[now].siz++;
        if (a[now].data<=x)
            if (a[now].ch[1]) now=a[now].ch[1];
            else f=0,a[now].ch[1]=id,a[id].fa=now;
        else
            if (a[now].ch[0]) now=a[now].ch[0];
            else f=0,a[now].ch[0]=id,a[id].fa=now;
    }
    splay(id,0);
}
int find_max(int now)
{
    while (a[now].ch[1]) now=a[now].ch[1];
    return now;
}
void del(int id)
{
    splay(id,0);
    if (a[id].siz==1) root=0;
    else if (!a[id].ch[0])
        root=a[id].ch[1],
        a[root].fa=0;
    else if (!a[id].ch[1])
        root=a[id].ch[0],
        a[root].fa=0;
    else
        splay(find_max(a[root].ch[0]),root),
        a[a[root].ch[1]].fa=a[root].ch[0],
        a[a[root].ch[0]].ch[1]=a[root].ch[1],
        a[a[root].ch[0]].fa=0,
        root=a[root].ch[0];
        ct(root);
}
main()
{
    scanf("%d%d",&n,&m);
    int x;
    if (m>(n/2)) {printf("Error!\n");return 0;}
    for (int i=1;i<=n;++i)
        scanf("%d",&x),
        insert(i,x);
    for (int i=1;i<=n;i++)
        L[i]=i-1,R[i]=i+1;
    L[1]=n;R[n]=1;
    int ans=0;
    for (;m;--m)
    {
        x=find_max(root);
        ans+=a[x].data;
        del(x);
        insert(x,a[L[x]].data+a[R[x]].data-a[x].data);
        del(L[x]);del(R[x]);
        int ll=L[x],rr=R[x];
        R[L[ll]]=x;L[x]=L[ll];
        L[R[rr]]=x;R[x]=R[rr];
    }
    printf("%d\n",ans);
}

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:126148次
    • 积分:4785
    • 等级:
    • 排名:第6047名
    • 原创:362篇
    • 转载:1篇
    • 译文:0篇
    • 评论:94条
    博客专栏
    最新评论