BZOJ3192: [JLOI2013]删除物品(splay)
Description
Input
Output
Sample Input
1
4
5
2
7
3
Sample Output
6
解题思路:
决策已经很明显了,找到最大的,把上面的压到另外一堆里。
考虑splay维护一下。
还要开long long.
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
#define lll tr[spc].ch[0]
#define rrr tr[spc].ch[1]
#define ls ch[0]
#define rs ch[1]
using std::swap;
const int N=;
typedef long long lnt;
struct data{
lnt Max_val;
lnt Where_is_Max_Val;
bool friend operator < (data x,data y)
{
return x.Max_val<y.Max_val;
}
lnt wp()
{
return Where_is_Max_Val;
}
};
struct trnt{
int ch[];
int fa;
int lzt;
lnt val;
data mxs;
lnt wgt;
}tr[N];
int siz;
int n1,n2;
int root1,root2;
int fst1,lst1;
int fst2,lst2;
lnt ans=;
lnt num[N];
data max(data a,data b)
{
if(a.Max_val<b.Max_val)
return b;
return a;
}
bool whc(int spc)
{
return tr[tr[spc].fa].rs==spc;
}
void res(int spc)
{
tr[spc].wgt=;
tr[spc].mxs=(data){tr[spc].val,spc};
return ;
}
void pushup(int spc)
{
res(spc);
if(lll)
{
tr[spc].wgt+=tr[lll].wgt;
tr[spc].mxs=max(tr[spc].mxs,tr[lll].mxs);
}
if(rrr)
{
tr[spc].wgt+=tr[rrr].wgt;
tr[spc].mxs=max(tr[spc].mxs,tr[rrr].mxs);
}
return ;
}
void trr(int spc)
{
if(!spc)
return ;
tr[spc].lzt^=;
swap(lll,rrr);
return ;
}
void pushdown(int spc)
{
if(tr[spc].lzt)
{
trr(lll);
trr(rrr);
tr[spc].lzt=;
}
return ;
}
void recal(int spc)
{
if(tr[spc].fa)
recal(tr[spc].fa);
pushdown(spc);
return ;
}
void rotate(int spc)
{
int f=tr[spc].fa;
bool k=whc(spc);
tr[f].ch[k]=tr[spc].ch[!k];
tr[spc].ch[!k]=f;
tr[tr[f].fa].ch[whc(f)]=spc;
tr[spc].fa=tr[f].fa;
tr[f].fa=spc;
tr[tr[f].ch[k]].fa=f;
pushup(f);
pushup(spc);
return ;
}
int splay(int spc,int f)
{
recal(spc);
while(tr[spc].fa!=f)
{
int ft=tr[spc].fa;
if(tr[ft].fa==f)
{
rotate(spc);
break;
}
if(whc(spc)^whc(ft))
rotate(spc);
else
rotate(ft);
rotate(spc);
}
return spc;
}
void build(int &spc,int l,int r,int f)
{
if(l>r)
return ;
spc=++siz;
int mid=(l+r)>>;
tr[spc].fa=f;
tr[spc].val=num[mid];
res(spc);
build(lll,l,mid-,spc);
build(rrr,mid+,r,spc);
pushup(spc);
return ;
}
int fstfind(int spc)
{
while(lll)
spc=lll;
return spc;
}
int lstfind(int spc)
{
while(rrr)
spc=rrr;
return spc;
}
int maxmin(int spc)
{
pushdown(spc);
spc=lll;
pushdown(spc);
while(rrr)
{
spc=rrr;
pushdown(spc);
}
return spc;
}
int minmax(int spc)
{
pushdown(spc);
spc=rrr;
pushdown(spc);
while(lll)
{
spc=lll;
pushdown(spc);
}
return spc;
}
int lstmax(int spc)
{
pushdown(spc);
if(lll)
return maxmin(spc);
recal(spc);
while(whc(spc)==)
spc=tr[spc].fa;
return tr[spc].fa;
}
int main()
{
scanf("%d%d",&n1,&n2);
for(int i=;i<=n1;i++)
scanf("%lld",&num[n1-i+]);
build(root1,,n1+,);
fst1=fstfind(root1);
lst1=lstfind(root1);
for(int i=;i<=n2;i++)
scanf("%lld",&num[n2-i+]);
build(root2,,n2+,);
fst2=fstfind(root2);
lst2=lstfind(root2);
for(int i=;i<=n1+n2;i++)
{
root1=splay(fst1,);
splay(lst1,root1);
root2=splay(fst2,);
splay(lst2,root2);
int spc1,spc2;
spc1=tr[tr[root1].rs].ls;
spc2=tr[tr[root2].rs].ls;
if(tr[spc1].mxs<tr[spc2].mxs)
{
root2=splay(tr[spc2].mxs.wp(),);
splay(lst2,root2);
int tmp=tr[tr[root2].rs].ls;
tr[tr[root2].rs].ls=;
pushup(tr[root2].rs);
pushup(root2);
ans+=tr[tmp].wgt;
trr(tmp);
int temp=root2;
root2=splay(maxmin(temp),);
splay(minmax(temp),root2);
tr[tr[root2].rs].ls=;
pushup(tr[root2].rs);
pushup(root2);
root1=splay(lstmax(lst1),);
splay(lst1,root1);
tr[tr[root1].rs].ls=tmp;
tr[tmp].fa=tr[root1].rs;
pushup(tr[root1].rs);
pushup(root1);
}else{
root1=splay(tr[spc1].mxs.wp(),);
splay(lst1,root1);
int tmp=tr[tr[root1].rs].ls;
tr[tr[root1].rs].ls=;
pushup(tr[root1].rs);
pushup(root1);
ans+=tr[tmp].wgt;
trr(tmp);
int temp=root1;
root1=splay(maxmin(temp),);
splay(minmax(temp),root1);
tr[tr[root1].rs].ls=;
pushup(tr[root1].rs);
pushup(root1);
root2=splay(lstmax(lst2),);
splay(lst2,root2);
tr[tr[root2].rs].ls=tmp;
tr[tmp].fa=tr[root2].rs;
pushup(tr[root2].rs);
pushup(root2);
}
}
printf("%lld\n",ans);
return ;
}
BZOJ3192: [JLOI2013]删除物品(splay)的更多相关文章
- [bzoj3192][JLOI2013]删除物品(树状数组)
3192: [JLOI2013]删除物品 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 872 Solved: 508[Submit][Status ...
- [bzoj3192][JLOI2013]删除物品_树状数组_栈
删除物品 bzoj-3192 JLOI-2013 题目大意:给你n个物品,分成2堆.所有的物品有不同的优先级.我只可以将一堆中的堆顶移动到另一个堆的堆顶.而如果当前物品是全局所有物品中优先级最高的,我 ...
- bzoj3192 [JLOI2013]删除物品
用数组表示两个栈,将两个栈的栈顶并在一起,用树状数组维护一下操作即可. 代码 #include<cstdio> #include<algorithm> #include< ...
- bzoj3192: [JLOI2013]删除物品(树状数组)
既然要从一个堆的堆顶按顺序拿出来放到第二个堆的堆顶,那么我们就可以把两个堆顶怼在一起,这样从一个堆拿到另一个堆只需要移动指针就好了. 换句话说,把1~n倒着,n+1到n+m正着,用一个指针把两个序列分 ...
- 洛谷 P3253 [JLOI2013]删除物品 解题报告
P3253 [JLOI2013]删除物品 题目描述 箱子再分配问题需要解决如下问题: (1)一共有\(N\)个物品,堆成\(M\)堆. (2)所有物品都是一样的,但是它们有不同的优先级. (3)你只能 ...
- 3192: [JLOI2013]删除物品
3192: [JLOI2013]删除物品 Time Limit: 10 Sec Memory Limit: 128 MB Submit: 1366 Solved: 794 [Submit][Statu ...
- BZOJ3192:[JLOI2013]删除物品——题解
https://www.lydsy.com/JudgeOnline/problem.php?id=3192 箱子再分配问题需要解决如下问题: (1)一共有N个物品,堆成M堆. (2)所有物品都是一样的 ...
- bzoj 3192: [JLOI2013]删除物品
Description 箱子再分配问题需要解决如下问题: (1)一共有N个物品,堆成M堆. (2)所有物品都是一样的,但是它们有不同的优先级. (3)你只能够移动某堆中位于顶端的物品. ( ...
- [JLOI2013]删除物品
嘟嘟嘟 只要每一次将优先级最高的上面的物品移走,就一定能保证是最优解. 所以我们只要想办法简化这个模拟移物品的过程,看完了题解后,发现可以这么想,我们可以把两个栈头碰头的挨在一起,然后设一个指针代表两 ...
随机推荐
- 在kettle中实现数据验证和检查
在kettle中实现数据验证和检查 在ETL项目,输入数据通常不能保证一致性.在kettle中有一些步骤能够实现数据验证或检查.验证步骤能够在一些计算的基础上验证行货字段:过滤步骤实现数据过滤:jav ...
- 用Struts2搭建一个登录例子【本人亲测好用】
今天尝试struts2的搭建,遇到不少的问题,终于一一解决,逛了很多地方,最终完成搭建 1.首先要下载struts2的一些组件,我下载的是版本2.3.4.1,Eclipse是4.6版本的.由于版本的不 ...
- MD markdown入门
1.Headings: 2.Phrase emphasis *italic text* **Bold text** 3.Listing items (在文字之前添加 + , - 或者 * ) -ite ...
- 2D上下文
js中说明的上下文表示的意思为C++中作用域(个人理解),因此2D上下文说明的是这个2D的作用域 像素:用来描述图片清晰度的小矩阵 填充和描边 填充:context.fillStyle = " ...
- mysql的my.cnf文件详解
一.缘由 最近要接手数据库的维护工作,公司首选MySQL.对于MySQL的理解,我认为很多性能优化工作.主从主主复制都是在调整参数,来适应不同时期不同数量级的数据. 故,理解透彻my.cnf里的参数是 ...
- SPI总线工作模式
一.SPI总线工作模式 SPI总线有四种工作模式,是由时钟极性选择(CPOL)和时钟相位选择(CPHA)决定的. CPOL = 0 ,SPI总线空闲为低电平,CPOL = 1, SPI总线空闲为高电平 ...
- 如何获取repeater某行第一列的值
<div> <asp:Repeater ID="Repeater1" runat="server" DataMember="Defa ...
- Floodlight中 处理packetin消息的顺序(2)
前面通过阅读代码知道了怎样推断各个模块处理某个消息的先后顺序.那么内部是怎样实现的呢? 每当一个模块表示对一个消息感兴趣的时候,就会调用IFloodlightProviderSer ...
- [DLX反复覆盖] hdu 2828 Lamp
题意: 有N个灯M个开关 每一个灯的ON和OFF状态都能控制一个灯是否亮 给出N行,代表对于每一个灯 哪些开关的哪个状态能够使得第i个灯亮 思路: 这里须要注意一个问题 假设开关1的ON 状态和开关2 ...
- Unix/Linux环境C编程新手教程(37) shell经常使用命令演练
cat命令 cat命令能够用来查看文件内容. cat [參数] 文件名称. grep-指定文件里搜索指定字符内容. Linux的文件夹或文件. -path '字串' 查找路径名匹配所给字串的全部 ...