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

原创 2016年08月29日 20:55:42

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);
}

版权声明:不转不是中国人!(滑稽)

相关文章推荐

[BZOJ4127][树链剖分][线段树][乱搞]Abs

题意给定一棵树,设计数据结构支持以下操作 1 u v d 表示将路径 (u,v) 加d 2 u v 表示询问路径 (u,v) 上点权绝对值的和想了半天不会做…… 搜了发题解因...

【Bzoj2151】种树

题意A城市有一个巨大的圆形广场,为了绿化环境和净化空气,市政府决定沿圆形广场外圈种一圈树。园林部门得到指令后,初步规划出n个种树的位置,顺时针编号1到n。并且每个位置都有一个美观度Ai,如果在这里种树...

bzoj 2151 种树

原题网址:http://www.lydsy.com/JudgeOnline/problem.php?id=2151 最容易想到的是O(n^2) dp。 这里有个优雅处理,就是当选一棵树...

bzoj 2151 种树(贪心+堆)(经典)

思路: 看到题,第一反应就是搜索,学了一年,还太水。。看了大神的博客。如下: 分析: 首先考虑如果没有“相邻位置不能都种”这一限制会怎么样。这时就是一个裸的贪心——按照A[i]从大到小排序,然后...

【国家集训队2011】【BZOJ2151】种树

Description A城市有一个巨大的圆形广场,为了绿化环境和净化空气,市政府决定沿圆形广场外圈种一圈树。园林部门得到指令后,初步规划出n个种树的位置,顺时针编号1到n。并且每个位置都有一个美观...

bzoj-2151 种树

题意: 给出一个n个点的环,每个点有一个有正有负的权值; 现要在其中选出m个互不相连的点,使权值和最大; 对于85%的数据:n 对于100%的数据:n 题解: 论如何出一道...

BZOJ 2151 种树 贪心 双向链表优化

给你一个nn个点的环,每个点有点权,在环上取出互不相邻的mm个点,求最大值 我们可以贪心,将所有的点扔入一个堆里 每次取出堆顶的元素,然后在双向链表中删去这个点 然而这样可能是错的,比如1354...

BZOJ 2151 种树 贪心

2151: 种树 Time Limit: 10 Sec  Memory Limit: 259 MBSubmit: 711  Solved: 396[Submit][Status][Discuss]A...

CodeForces 723C-Polycarp at the Radio(模拟 贪心 vector乱搞)

C. Polycarp at the Radio time limit per test2 seconds memory limit per test256 megabytes inputsta...

[BZOJ1691][Usaco2007 Dec]挑剔的美食家(贪心+splay)

在那将嘴唇咬紧的夜晚 听到的是谁的声音 在月光下不断回响 是这个声音鼓舞着我前行
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

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