线段树上\(DP\)

首先发现,每个数肯定是向自己的前驱或后继连边的。

则我们开一棵权值线段树,其中每一个节点记录一个\(f_{0/1,0/1}\),表示在这个区间左、右端点是否连过边的情况下,使这个区间符合条件的最小代价。

合并时考虑如果左儿子的右端点或右儿子的左端点中有一个没有连过边,就必须连边,否则就不连边。

然后我的写法比较蠢,不知道为什么当左右儿子中某个节点只有一个数时需要特判处理。

最后答案就是根节点的\(f_{1,1}\)。

具体详见代码。

代码

#include<bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define Reg register
#define RI Reg int
#define Con const
#define CI Con int&
#define I inline
#define W while
#define N 200000
#define V 1000000000
#define LV 30
#define LL long long
#define INF 1e18
#define min(x,y) ((x)<(y)?(x):(y))
#define Gmin(x,y) (x>(y)&&(x=(y)))
using namespace std;
int n,Qt,a[2*N+5];
class FastIO
{
private:
#define FS 100000
#define tc() (A==B&&(B=(A=FI)+fread(FI,1,FS,stdin),A==B)?EOF:*A++)
#define pc(c) (C==E&&(clear(),0),*C++=c)
#define tn (x<<3)+(x<<1)
#define D isdigit(c=tc())
int T;char c,*A,*B,*C,*E,FI[FS],FO[FS],S[FS];
public:
I FastIO() {A=B=FI,C=FO,E=FO+FS;}
Tp I void read(Ty& x) {x=0;W(!D);W(x=tn+(c&15),D);}
Tp I void write(Ty x) {W(S[++T]=x%10+48,x/=10);W(T) pc(S[T--]);}
Tp I void writeln(Con Ty& x) {write(x),pc('\n');}
I void clear() {fwrite(FO,1,C-FO,stdout),C=FO;}
#undef D
}F;
class SegmentTreeSolver
{
private:
template<int SZ> class SegmentTree//线段树
{
private:
#define F5(x,l,r)\
O[x].f[l][r]=O[O[x].S[0]].f[l][1]+O[O[x].S[1]].f[1][r],\
Gmin(O[x].f[l][r],O[O[x].S[0]].f[l][0]+O[O[x].S[1]].f[0][r]+O[O[x].S[1]].L-O[O[x].S[0]].R),\
Gmin(O[x].f[l][r],O[O[x].S[0]].f[l][0]+O[O[x].S[1]].f[1][r]+O[O[x].S[1]].L-O[O[x].S[0]].R),\
Gmin(O[x].f[l][r],O[O[x].S[0]].f[l][1]+O[O[x].S[1]].f[0][r]+O[O[x].S[1]].L-O[O[x].S[0]].R)//普通情况下转移
int n,rt,Nt;struct node//维护节点信息
{
int Ex,L,R,S[2];LL f[2][2];
I node(CI x=0):Ex(0),L(x),R(x),S({0,0}),f({{0,INF},{INF,INF}}){}
I void operator = (Con node& o)
{
Ex=o.Ex,L=o.L,R=o.R,f[0][0]=o.f[0][0],f[0][1]=o.f[0][1],
f[1][0]=o.f[1][0],f[1][1]=o.f[1][1];
}
}O[SZ+5];
I void PU(CI x)//上传信息
{
if(!O[O[x].S[0]].Ex) return (void)(O[x]=O[O[x].S[1]]);//如果没有左儿子
if(!O[O[x].S[1]].Ex) return (void)(O[x]=O[O[x].S[0]]);//如果没有右儿子
O[x].Ex=1,O[x].L=O[O[x].S[0]].L,O[x].R=O[O[x].S[1]].R;//上传基础信息
if(O[O[x].S[0]].L==O[O[x].S[0]].R&&O[O[x].S[1]].L==O[O[x].S[1]].R)//合并两个单点
{
O[x].f[0][0]=0,O[x].f[1][1]=O[O[x].S[1]].L-O[O[x].S[0]].R,
O[x].f[0][1]=O[x].f[1][0]=INF;return;
}
if(O[O[x].S[0]].L==O[O[x].S[0]].R)//合并单点和区间
{
O[x].f[1][0]=min(O[O[x].S[1]].f[0][0],O[O[x].S[1]].f[1][0])+O[O[x].S[1]].L-O[O[x].S[0]].R,
O[x].f[1][1]=min(O[O[x].S[1]].f[0][1],O[O[x].S[1]].f[1][1])+O[O[x].S[1]].L-O[O[x].S[0]].R,
O[x].f[0][0]=O[O[x].S[1]].f[1][0],O[x].f[0][1]=O[O[x].S[1]].f[1][1];return;
}
if(O[O[x].S[1]].L==O[O[x].S[1]].R)//合并区间和单点
{
O[x].f[0][1]=min(O[O[x].S[0]].f[0][0],O[O[x].S[0]].f[0][1])+O[O[x].S[1]].L-O[O[x].S[0]].R,
O[x].f[1][1]=min(O[O[x].S[0]].f[1][0],O[O[x].S[0]].f[1][1])+O[O[x].S[1]].L-O[O[x].S[0]].R,
O[x].f[0][0]=O[O[x].S[0]].f[0][1],O[x].f[1][0]=O[O[x].S[0]].f[1][1];return;
}
F5(x,0,0),F5(x,0,1),F5(x,1,0),F5(x,1,1);
}
I void Upt(CI x,CI v,CI l,CI r,int& rt)//单点修改
{
if(!rt&&(rt=++Nt),l==r) return (void)(!O[rt].Ex&&(O[rt]=node(l),0),O[rt].Ex+=v);
RI mid=l+r>>1;x<=mid?Upt(x,v,l,mid,O[rt].S[0]):Upt(x,v,mid+1,r,O[rt].S[1]),PU(rt);
}
public:
I void Init(CI _n) {n=_n;}I void Upt(CI x,CI v) {Upt(x,v,1,n,rt);}
I LL Qry() {return O[rt].f[1][1];}//询问
};SegmentTree<N*LV> S;
public:
I void Solve()
{
RI i,op,x;for(S.Init(V),i=1;i<=n;++i) S.Upt(a[i],1);//初始化
W(Qt--) F.read(op),F.read(x),S.Upt(x,op==1?1:-1),F.writeln(S.Qry());//处理操作
}
}S;
int main()
{
freopen("set.in","r",stdin),freopen("set.out","w",stdout);
RI i;for(F.read(n),F.read(Qt),i=1;i<=n;++i) F.read(a[i]);
return sort(a+1,a+n+1),S.Solve(),F.clear(),0;
}

【2019.8.6 慈溪模拟赛 T3】集合(set)(线段树上DP)的更多相关文章

  1. 【2019.8.11上午 慈溪模拟赛 T3】欢迎回来(back)(设阈值+莫队)

    设阈值 考虑对于询问的\(d\)设阈值进行分别处理. 对于\(d\le\sqrt{max\ d}\)的询问,我们可以\(O(n\sqrt{max\ d})\)预处理答案,\(O(1)\)输出. 对于\ ...

  2. 【2019.8.15 慈溪模拟赛 T1】插头(plugin)(二分+贪心)

    二分 首先,可以发现,最后的答案显然满足可二分性,因此我们可以二分答案. 然后,我们只要贪心,就可以验证了. 贪心 不难发现,肯定会优先选择能提供更多插座的排插,且在确定充电器个数的情况下,肯定选择能 ...

  3. 【2019.10.7 CCF-CSP-2019模拟赛 T3】未知的数组(unknown)(并查集+动态规划)

    预处理 考虑模数\(10\)是合数不好做,所以我们可以用一个常用套路: \(\prod_{i=l}^ra_i\equiv x(mod\ 10)\)的方案数等于\(\prod_{i=l}^ra_i\eq ...

  4. 【2019.8.20 NOIP模拟赛 T3】小X的图(history)(可持久化并查集)

    可持久化并查集 显然是可持久化并查集裸题吧... 就是题面长得有点恶心,被闪指导狂喷. 对于\(K\)操作,直接\(O(1)\)赋值修改. 对于\(R\)操作,并查集上直接连边. 对于\(T\)操作, ...

  5. 【2019.8.15 慈溪模拟赛 T2】组合数(binom)(卢卡斯定理+高维前缀和)

    卢卡斯定理 题目中说到\(p\)是质数. 而此时要求组合数向质数取模的结果,就可以用卢卡斯定理: \[C_x^y=C_{x\ div\ p}^{y\ div\ p}\cdot C_{x\ mod\ p ...

  6. 【2019.8.6 慈溪模拟赛 T2】树上路径(tree)(Trie)

    从暴力考虑转化题意 考虑最暴力的做法,我们枚举路径的两端,然后采用类似求树上路径长度的做法,计算两点到根的贡献,然后除去\(LCA\)到根的贡献两次. 即,设\(v_i\)为\(i\)到根路径上的边权 ...

  7. 【2019.8.7 慈溪模拟赛 T2】环上随机点(ran)(自然算法)

    简单声明 我是蒟蒻不会推式子... 所以我用的是乱搞做法... 大自然的选择 这里我用的乱搞做法被闪指导赐名为"自然算法",对于这种输入信息很少的概率题一般都很适用. 比如此题,对 ...

  8. 【2019.8.8 慈溪模拟赛 T1】开箱(chest)(暴力DP水过)

    转化题意 这题目乍一看十分玄学,完全不可做. 但实际上,假设我们在原序列从小到大排序之后,选择开的宝箱编号是\(p_{1\sim Z}\),则最终答案就是: \[\sum_{i=1}^Za_{p_i} ...

  9. 【2019.8.8 慈溪模拟赛 T2】query(query)(分治+分类讨论)

    分治 首先,我们考虑分治处理此问题. 每次处理区间\([l,r]\)时,我们先处理完\([l,mid]\)和\([mid+1,r]\)两个区间的答案,然后我们再考虑计算左区间与右区间之间的答案. 处理 ...

随机推荐

  1. antd配置config-overrides.js文件

    下载antd 包 npm install antd 下载依赖包(定义组件按需求打包) npm install react-app-rewired customize-cra babel-plugin- ...

  2. 如何创建Azure Face API和计算机视觉Computer Vision API

    在人工智能技术飞速发展的当前,利用技术手段实现人脸识别.图片识别已经不是什么难事.目前,百度.微软等云计算厂商均推出了人脸识别和计算机视觉的API,其优势在于不需要搭建本地环境,只需要通过网络交互,就 ...

  3. Tensorflow.nn 核心模块详解

    看过前面的例子,会发现实现深度神经网络需要使用 tensorflow.nn 这个核心模块.我们通过源码来一探究竟. # Copyright 2015 Google Inc. All Rights Re ...

  4. 《细说PHP》 第四版 样章 第二章 PHP的应用与发展 4

    2.4  PHP的发展 最初创建时,PHP是一个简单的用Perl语言编写的程序,只是为了统计自己的网站有多少访问者.后来又用C语言重新编写,多年来,PHP经过无数开源贡献者的不断迭代,历经数个版本,已 ...

  5. tensorflow slim代码使用

    此处纯粹作为个人学习使用,原文连接:https://www.jianshu.com/p/dc24e54aec81 这篇文章是借鉴很多博文的,作为一个关于slim库的总结 导入slim模块 import ...

  6. 实例演示 C# 中 Dictionary<Key, Value> 的检索速度远远大于 hobbyList.Where(c => c.UserId == user.Id)

    前言 我们知道,有时候在一些项目中,为了性能,往往会一次性加载很多条记录来进行循环处理(备注:而非列表呈现).比如:从数据库中加载 10000 个用户,并且每个用户包含了 20  个“爱好”,在 Wi ...

  7. C# event

    class Program { static void Main(string[] args) { Thermostat thermostat = new Thermostat(); Heater h ...

  8. github pages与travis ci运作原理

    当说到自动部署的时候,我很反感那些一上来就balabala说怎么操作的博文文章,照着别人的做法有样学样,经常会因为与自己项目实际情况不符而出现各种问题. 比如说github和travis,首先应该搞明 ...

  9. 如何编写 maptalks plugin

    前面写过 maptalks plugin ( ArcGISTileLayer ),有读者留言说文章写得太精简,根据文章给出的核心代码没办法写出一个完整的 plugin ( 文中有完整 demo 地址, ...

  10. DevOps 工程师成长日记系列二:配置

    原文地址:https://medium.com/@devfire/how-to-become-a-devops-engineer-in-six-months-or-less-part-2-config ...