CF765F Souvenirs

【CF765F】Souvenirs 主席树 - CQzhangyu - 博客园

其实不用主席树

感觉像是离线问题

但是不能支持差分。分治又处理不了

考虑按照右端点排序,线段树维护左端点为i的时候的答案

然后trick一下,把求ansl,变成求min(ansl....ansr),这样可以少更新很多

先把|ai-aj|变成j<i,aj>=ai这样找,然后再反过来做一次。

新加入的a[i],找之前第一个大于a[i]的a[pos],(pos是所在位置)

在pos位置更新答案。

对于k<pos,若a[k]>=a[pos],显然再和a[i]做贡献没有意义了。取到ansk一定能取到anspos

设mid=(a[pos]+a[i])/2,发现,对于k<pos,且a[k]>mid,a[k]和a[pos]做贡献一定更优(这在反过来的时候会考虑到),并且取到ansk一定能取到和pos做的贡献

所以只用考虑k<=mid,规模每次/2,log(max{ai})次logn

找pos,可以用动态开点线段树,每次找权值范围内最晚出现的。

复杂度:O(nlognlogai)

#include<bits/stdc++.h>
#define reg register int
#define il inline
#define fi first
#define se second
#define mk(a,b) make_pair(a,b)
#define numb (ch^'0')
using namespace std;
typedef long long ll;
template<class T>il void rd(T &x){
char ch;x=;bool fl=false;
while(!isdigit(ch=getchar()))(ch=='-')&&(fl=true);
for(x=numb;isdigit(ch=getchar());x=x*+numb);
(fl==true)&&(x=-x);
}
template<class T>il void output(T x){if(x/)output(x/);putchar(x%+'');}
template<class T>il void ot(T x){if(x<) putchar('-'),x=-x;output(x);putchar(' ');}
template<class T>il void prt(T a[],int st,int nd){for(reg i=st;i<=nd;++i) ot(a[i]);putchar('\n');} namespace Miracle{
const int N=4e5+;
const int inf=0x3f3f3f3f;
int n,m;
int ans[N];
int a[N];
struct que{
int l,r,id;
}q[N];
bool cmp1(que a,que b){
return a.r<b.r;
}
bool cmp2(que a,que b){
return a.l>b.l;
} #define mid ((l+r)>>1)
namespace tr1{
int rt;
struct node{
int ls,rs;
int tim;
node(){
tim=;
}
}t[N*];
int tot;
void pushup(int x){
t[x].tim=max(t[t[x].ls].tim,t[t[x].rs].tim);
}
int fin(int x,int l,int r,int L,int R){
if(L>R) return ;
if(!x) return ;
if(L<=l&&r<=R){
if(l==r) return t[x].tim;
if(t[t[x].ls].tim>t[t[x].rs].tim) return fin(t[x].ls,l,mid,L,R);
else return fin(t[x].rs,mid+,r,L,R);
}
if(R<=mid) return fin(t[x].ls,l,mid,L,R);
if(L>mid) return fin(t[x].rs,mid+,r,L,R);
return max(fin(t[x].ls,l,mid,L,R),fin(t[x].rs,mid+,r,L,R));
}
void chan(int &x,int l,int r,int p,int ti){
if(!x) x=++tot;
if(l==r){
t[x].tim=max(t[x].tim,ti);return;
}
if(p<=mid) chan(t[x].ls,l,mid,p,ti);
else chan(t[x].rs,mid+,r,p,ti);
pushup(x);
}
void init(){
t[].tim=;
tot=;
}
void clear(){
for(reg i=;i<=tot;++i){
t[i].ls=t[i].rs=;
t[i].tim=;
}
tot=;rt=;
} }
namespace tr2{
#define ls (x<<1)
#define rs (x<<1|1)
int ans[*N];
void build(int x,int l,int r){
if(l==r){
ans[x]=inf;return ;
}
ans[x]=inf;
build(x<<,l,mid);build(x<<|,mid+,r);
}
void pushup(int x){
ans[x]=min(ans[ls],ans[rs]);
}
void upda(int x,int l,int r,int p,int c){
if(l==r){
ans[x]=min(ans[x],c);return;
}
if(p<=mid) upda(ls,l,mid,p,c);
else upda(rs,mid+,r,p,c);
pushup(x);
}
int query(int x,int l,int r,int L,int R){
if(L<=l&&r<=R) return ans[x];
if(R<=mid) return query(ls,l,mid,L,R);
if(L>mid) return query(rs,mid+,r,L,R);
return min(query(ls,l,mid,L,R),query(rs,mid+,r,L,R));
}
void clear(){
memset(ans,0x3f,sizeof ans);
} } int main(){
// cout<<" 23333 "<<endl;
rd(n);
int lim=;
for(reg i=;i<=n;++i) rd(a[i]),lim=max(lim,a[i]);
// cout<<" after rd "<<lim<<endl;
rd(m);
for(reg i=;i<=m;++i){
rd(q[i].l);rd(q[i].r);q[i].id=i;
}
// cout<<" after rd "<<endl;
memset(ans,0x3f,sizeof ans);
sort(q+,q+m+,cmp1);
int ptr=;
// cout<<" sort1 "<<endl;
tr2::build(,,n);
tr1::init();
// cout<<" built "<<endl; for(reg i=;i<=n;++i){
// cout<<" ii "<<i<<" ptr "<<ptr<<endl;
if(i!=){
int pos=tr1::fin(tr1::rt,,lim,a[i],lim);
while(pos){
// cout<<" pos "<<pos<<endl;
tr2::upda(,,n,pos,a[pos]-a[i]);
// cout<<" after tr2 upda "<<endl;
pos=tr1::fin(tr1::rt,,lim,a[i],min(a[pos]-,(a[pos]+a[i])/));
}
}
// cout<<" over udpa "<<endl;
while(ptr<=m&&q[ptr].r==i){
ans[q[ptr].id]=min(ans[q[ptr].id],tr2::query(,,n,q[ptr].l,i));
++ptr;
}
tr1::chan(tr1::rt,,lim,a[i],i);
}
// cout<<" turn1 "<<endl; tr2::clear();
tr1::clear();
tr2::build(,,n); sort(q+,q+m+,cmp2);
ptr=;
// cout<<" st2 "<<endl;
for(reg i=n;i>=;--i){
if(i!=n){
int pos=tr1::fin(tr1::rt,,lim,a[i],lim);
while(pos){
pos=n-pos+;
tr2::upda(,,n,pos,a[pos]-a[i]);
pos=tr1::fin(tr1::rt,,lim,a[i],min(a[pos]-,(a[pos]+a[i])/));
}
}
while(ptr<=m&&q[ptr].l==i){
ans[q[ptr].id]=min(ans[q[ptr].id],tr2::query(,,n,i,q[ptr].r));
++ptr;
}
tr1::chan(tr1::rt,,lim,a[i],n-i+);
}
// cout<<" turn2 "<<endl;
// return 0;
for(reg i=;i<=m;++i){
printf("%d\n",ans[i]);
}
return ;
} }
signed main(){
// freopen("data.in","r",stdin);
// freopen("my.out","w",stdout);
Miracle::main();
return ;
} /*
Author: *Miracle*
*/

CF765F Souvenirs的更多相关文章

  1. CF765F Souvenirs 解题报告

    CF765F Souvenirs 题意翻译 给出\(n(2 \le n \le 10^5 )\) ,一个长为\(n\)的序列\(a(0 \le a_i \le 10^9 )\). 给出\(m(1\le ...

  2. CF765F Souvenirs 离线+线段树+主席树

    $ \color{#0066ff}{ 题目描述 }$ A县旁,连绵着一条长度为 n 的山脉,这条山脉由 n 座山峰组成,第 i 座山 峰的高度为 ai.作为著名的旅游县城,每天来到山脉游玩的旅客络绎不 ...

  3. 多校联训 DS 专题

    CF1039D You Are Given a Tree 容易发现,当 \(k\) 不断增大时,答案不断减小,且 \(k\) 的答案不超过 \(\lfloor\frac {n}{k}\rfloor\) ...

  4. 【CF765F】Souvenirs 主席树

    [CF765F]Souvenirs 题意:给你一个长度为n的序列{ai},有m个询问,每次询问给出l,r,问在所有$l\le x < y\le r$中,$|a_x-a_y|$的最小值是多少. $ ...

  5. 【CF765F】Souvenirs

    [CF765F]Souvenirs 题面 洛谷 题解 我们可以发现,对于某个右端点\(i\),左端点\(j\)在由\(i\rightarrow 1\)的过程中,每一段的答案是单调不增的,由这个性质,我 ...

  6. [HDU 2126] Buy the souvenirs (动态规划)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2126 题意:给你n个物品,m元钱,问你最多能买个多少物品,并且有多少种解决方案. 一开始想到的是,先解 ...

  7. HDU 2126 Buy the souvenirs (01背包,输出方案数)

    题意:给出t组数据 每组数据给出n和m,n代表商品个数,m代表你所拥有的钱,然后给出n个商品的价值 问你所能买到的最大件数,和对应的方案数.思路: 如果将物品的价格看做容量,将它的件数1看做价值的话, ...

  8. HDU 2126 (背包方法数) Buy the souvenirs

    DP还有很长很长一段路要走.. 题意:给出n纪念品的价格和钱数m,问最多能买多少件纪念品和买这些数量的纪念品的方案数. 首先,求能买最多的纪念品的数量,用贪心法可以解决.将价钱排序,然后从最便宜的开始 ...

  9. HDU-2126 Buy the souvenirs

    数组01背包. http://acm.hdu.edu.cn/showproblem.php?pid=2126 http://blog.csdn.net/crazy_ac/article/details ...

随机推荐

  1. Android开发如何轻松实现基于Tesseract的Android OCR应用程序

    介绍 此应用程序使用Tesseract 3的Tesseract OCR引擎,该引擎通过识别字符模式( https://github.com/tesseract-ocr/tesseract )来工作. ...

  2. Go-Ethereum 1.7.2 结合 Mist 0.9.2 实现众筹合约的实例

    目录 目录 1.什么是ICO? 2.众筹的奖励-代币 3.众筹合约的完善 3.1.设置众筹合约中使用的代币 3.2.众筹合约的基本设置 3.3.让众筹合约接收以太币 3.4.检测众筹合约是否完成 3. ...

  3. ASP.NET Core 入门教程 6、ASP.NET Core MVC 视图布局入门

    一.前言 1.本教程主要内容 ASP.NET Core MVC (Razor)视图母版页教程 ASP.NET Core MVC (Razor)带有Section的视图母版页教程 ASP.NET Cor ...

  4. SQL SERVER 执行动态SQL EXEC

    :普通SQL语句可以用Exec执行 eg: Select * from tableName Exec('select * from tableName') Exec sp_executesql N's ...

  5. python--继承--方法的重写---和父类的扩展

    1.方法的重写 父类的方法不能满足子类的需要,可以对方法重写 具体的实现方式,就相当于在子类中定义了一个和父类同名的方法并实现 重写之后只会对子类的方法调用,而不会调用父类封装的方法 2.对父类方法进 ...

  6. PHP生成PDF并转换成图片爬过的坑

    需求描述:根据订单通过模板合同生成新的PDF合同通过e签宝签约后转为图片给用户下载. 需求整理: 1.如何生成PDF文件:使用TCPDF扩展生成.思考: ⑴为了方便将模板中的固定占位符替换为订单中的内 ...

  7. SQLServer之索引简介

    索引设计基础知识 索引是与表或视图关联的磁盘上结构,可以加快从表或视图中检索行的速度. 索引包含由表或视图中的一列或多列生成的键. 这些键存储在一个结构(B 树)中,使 SQL Server 可以快速 ...

  8. Eclipse链接数据库

    在eclipse中找到数据库 选择数据库 然后点击next 填写数据库信息 选择需要执行的SQL语句 ALT+X 或者 右键点击execute selected text: 执行结果: 有问题请在评论 ...

  9. php7 的yum源

    yum源默认的版本太低了,手动安装有一些麻烦,想采用Yum更新安装的可以使用下面的方案: 1.检查当前安装的PHP包 yum list installed | grep php 如果有安装的PHP包, ...

  10. Redis数据持久化、数据备份、数据的故障恢复

    1.redis持久化的意义----redis故障恢复 在实际的生产环境中,很可能会遇到redis突然挂掉的情况,比如redis的进程死掉了.电缆被施工队挖了(支付宝例子)等等,总之一定会遇到各种奇葩的 ...