【2019.8.6 慈溪模拟赛 T3】集合(set)(线段树上DP)
线段树上\(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)的更多相关文章
- 【2019.8.11上午 慈溪模拟赛 T3】欢迎回来(back)(设阈值+莫队)
设阈值 考虑对于询问的\(d\)设阈值进行分别处理. 对于\(d\le\sqrt{max\ d}\)的询问,我们可以\(O(n\sqrt{max\ d})\)预处理答案,\(O(1)\)输出. 对于\ ...
- 【2019.8.15 慈溪模拟赛 T1】插头(plugin)(二分+贪心)
二分 首先,可以发现,最后的答案显然满足可二分性,因此我们可以二分答案. 然后,我们只要贪心,就可以验证了. 贪心 不难发现,肯定会优先选择能提供更多插座的排插,且在确定充电器个数的情况下,肯定选择能 ...
- 【2019.10.7 CCF-CSP-2019模拟赛 T3】未知的数组(unknown)(并查集+动态规划)
预处理 考虑模数\(10\)是合数不好做,所以我们可以用一个常用套路: \(\prod_{i=l}^ra_i\equiv x(mod\ 10)\)的方案数等于\(\prod_{i=l}^ra_i\eq ...
- 【2019.8.20 NOIP模拟赛 T3】小X的图(history)(可持久化并查集)
可持久化并查集 显然是可持久化并查集裸题吧... 就是题面长得有点恶心,被闪指导狂喷. 对于\(K\)操作,直接\(O(1)\)赋值修改. 对于\(R\)操作,并查集上直接连边. 对于\(T\)操作, ...
- 【2019.8.15 慈溪模拟赛 T2】组合数(binom)(卢卡斯定理+高维前缀和)
卢卡斯定理 题目中说到\(p\)是质数. 而此时要求组合数向质数取模的结果,就可以用卢卡斯定理: \[C_x^y=C_{x\ div\ p}^{y\ div\ p}\cdot C_{x\ mod\ p ...
- 【2019.8.6 慈溪模拟赛 T2】树上路径(tree)(Trie)
从暴力考虑转化题意 考虑最暴力的做法,我们枚举路径的两端,然后采用类似求树上路径长度的做法,计算两点到根的贡献,然后除去\(LCA\)到根的贡献两次. 即,设\(v_i\)为\(i\)到根路径上的边权 ...
- 【2019.8.7 慈溪模拟赛 T2】环上随机点(ran)(自然算法)
简单声明 我是蒟蒻不会推式子... 所以我用的是乱搞做法... 大自然的选择 这里我用的乱搞做法被闪指导赐名为"自然算法",对于这种输入信息很少的概率题一般都很适用. 比如此题,对 ...
- 【2019.8.8 慈溪模拟赛 T1】开箱(chest)(暴力DP水过)
转化题意 这题目乍一看十分玄学,完全不可做. 但实际上,假设我们在原序列从小到大排序之后,选择开的宝箱编号是\(p_{1\sim Z}\),则最终答案就是: \[\sum_{i=1}^Za_{p_i} ...
- 【2019.8.8 慈溪模拟赛 T2】query(query)(分治+分类讨论)
分治 首先,我们考虑分治处理此问题. 每次处理区间\([l,r]\)时,我们先处理完\([l,mid]\)和\([mid+1,r]\)两个区间的答案,然后我们再考虑计算左区间与右区间之间的答案. 处理 ...
随机推荐
- BERT-wwm、BERT-wwm-ext、RoBERTa、SpanBERT、ERNIE2
一.BERT-wwm wwm是Whole Word Masking(对全词进行Mask),它相比于Bert的改进是用Mask标签替换一个完整的词而不是子词,中文和英文不同,英文中最小的Token就是一 ...
- 【C#】C#获取本地的内网(局域网)和外网(公网)IP地址的方法
1.获取本机的IP地址集合: /// <summary> /// 获取本机所有ip地址 /// </summary> /// <param name="netT ...
- umi+dva+antd新建项目(亲测可用)
首先全局安装dva+umiumi:npm install -g umidva:npm install -g dva-cli 通过脚手架创建项目 一: mkdir myapp && cd ...
- 【转】Ubuntu 16 安装 python 依赖出现 error: command 'i686-linux-gnu-gcc' failed with exit status 1
问题 在 Ubuntu 下安装 python 依赖的时候出现以下错误 build/temp.linux-i686-3.5/_openssl.c:498:30: fatal error: openssl ...
- LeetCode 1:两数之和 Two Sum
题目: 给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标. 你可以假设每种输入只会对应一个答案.但是,你不能重复利用这个数组中 ...
- 《细说PHP》第四版 样章 第18章 数据库抽象层PDO 5
18.5 使用PDO对象 PDO扩展类库为PHP访问数据库定义了一个轻量级.一致性的接口,它提供了一个数据访问抽象层,这样,无论使用什么数据库,都可以通过一致的函数执行查询和获取数据,大大简化了数据 ...
- MongoDB系列---集合与文档操作03
MongoDB-——Collection 学习大纲: 1.集合操作 2.文档操作 知识回顾: 上一篇我们讲述了如何对MongoDB的权限和用户进行日常的基本操作,来达到我们对数据库的基本安全保障. 一 ...
- C# - WinFrm应用程序MessageBox自动关闭小实验
概述 在程序中MessageBox弹出的对话框,用于向用户展示消息,这是一个模式窗口,可阻止应用程序中的其他操作,直到用户将其关闭.但是有时候在自动化程序中,如果弹出对话框,程序将会中断,等待人工的干 ...
- python处理oracle数据库的返回数据
上代码: import SqlHelper.ORACLE as ORA import pandas as pd if __name__ == '__main__': #连接数据库 ms = ORA.O ...
- python连接Oracle工具类
上代码: # -*- coding:utf-8 -*- import cx_Oracle import pandas as pd class ORACLE(object): def __init__( ...