本来并不打算出原创题的,此题集CF542A和sk的灵感而成,算个半原创吧。

题目大意:

给定有$n$个元素的集合$P$,其中第$i$个元素中包含$L_i,R_i,V_i$三个值。

给定另一个有$n$个元素的集合$Q$,其中第$i$个元素包含$A_i,B_i,C_i$三个值。

选择集合$P$中第$x$个元素和集合$Q$中第$y$个元素的收益为$(r-l+1)*V_x*C_y$,其中$[l,r]$为$[L_i,R_i]$和$[A_i,B_i]$的交集。你需要在集合$P$,$Q$中分别选出一个元素,使得收益最大

数据范围:

子任务一:满足$n≤5000$

子任务二:满足$V_i=1$。

子任务三:满足$L_i=A_i=1$。

子任务四:满足$n≤10^5$

对于全部数据,所有数$≤10^5$,且$L_i≤R_i,A_i≤B_i$。

子任务一:暴力

子任务二:该子任务为CF542A:

这里有一个题解,看情况三和情况四就行了

子任务三:

不难发现该情况下,对于任意的$i,j$必有$L_i≤A_j,B_j≤R_i$,或者$A_j≤L_i,R_i≤B_j$。

我们把$P$和$Q$中所有元素都丢入一个数组中按右端点排序,同时我们种一棵线段树。

若当前元素原先在$P$中,我们用$(R_i-L_i+1)\times V_i$更新第$L_i$个位置的值(取max)

否则,我们查询区间$[A_i,B_i]$中的最大值,将该值乘上$C_i$后更新答案。

不难发现此方法可以处理所有$Q_i$包含$P_j$的情况。

对于$P_i$包含$Q_j$的情况,我们交换下两个集合再处理一次就好了。

子任务四:

首先要处理一下$P_i$包含$Q_i$或者$Q_i$包含$P_i$的情况,直接用子任务三的方式处理一下就行了。

我们将$P$中第$i$个元素看成一个定义域在$[L_i,R_i]$间的函数,我们把这个函数写作$F_i(x)$。

不难发现$F_i(x)=V_ix-(L_i-1)\times V_i$。

为了方便接下来的表述,我们将$F_i(x)$更改为如下形式:

$F_i(x)=\begin{cases} V_ix-(L_i-1)\times V_i \ \ \ x\in[L_i,R_i] \\ 0\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ x\notin[L_i,R_i]\end{cases}$

这是个分段函数

我们在$Q$中找出第y个元素$Q_y$,若存在$i$满足$A_y≤L_i$,则$Q_y$与$P_i$产生的收益为$C_y\times F_i(B_y)$。

最终答案显然为$max(C_y\times F_i(B_y))$。

按照子任务三的套路,我们把$P$和$Q$中所有元素都丢入一个数组中按左端点排序,维护一个保存函数的集合$S$

定义$S(x)=max_{F∈S}F(x)$

我们从大到小从数组中取出元素

若当前元素原先在$P$中,我们求出该元素对应的函数,并把它丢入$S$中。

否则,我们用$C_i\times S(B_i)$更新答案。

该做法复杂度显然是$O(nT_s)$,其中$T_s$表示求$S(x)$的复杂度。

我们不难想到$T_s=O(n)$的做法,但是不够优美。

我们考虑种一棵线段树,线段树的每个节点分别维护一个支持插入函数的半平面交。

如果我们要加入一个定义域在$[l,r]$的一次函数$f(x)$,就在线段树对应的区间上插入这个函数即可。

对于$S(x)$操作,我们只需要找出所有包含$x$的区间,在这些区间上的半平面交上求值即可。

单次插入的复杂度均摊为$O(log^2\ n)$ 单次查询的复杂度为$O(log^2\ n)$。

然而该方法只能处理出$Q_i$在$P_j$左边的情况。$Q_i$在$P_j$右边的情况我们交换一下两个集合再跑一遍就行了。

所以这是一道扫描线+线段树维护动态半平面的题目

总复杂度就是$O(n\ log^2\  n)$,空间复杂度$O(n\ log\ n)$。

完结撒花

 #include<bits/stdc++.h>
#define M 100010
#define L long long
#define mid ((aa[x].l+aa[x].r)>>1)
#define S set<line>::iterator
using namespace std; int n,N=,up=; L ans=;
struct lr{
int l,r,val;
void rd(){scanf("%d%d%d",&l,&r,&val); up=max(up,r);}
}a[M],b[M];
void swapAB(){for(int i=;i<=n;i++) swap(a[i],b[i]);}
struct ask{
int id,isa; ask(){id=isa=;}
ask(int ID,int ISa){id=ID; isa=ISa;}
friend bool operator <(ask A,ask B){
int vala=A.isa?a[A.id].l:b[A.id].l;
int valb=B.isa?a[B.id].l:b[B.id].l;
if(vala!=valb) return vala<valb;
return A.isa>B.isa;
}
}p[M*]; namespace SolveContains{
struct seg{int l,r;L maxn;}aa[<<];
void build(int x,int l,int r){
aa[x].l=l; aa[x].r=r; aa[x].maxn=; if(l==r) return;
build(x<<,l,mid); build(x<<|,mid+,r);
}
void updata(int x,int k,L val){
aa[x].maxn=max(aa[x].maxn,val);
if(aa[x].l==aa[x].r) return;
if(k<=mid) updata(x<<,k,val);
else updata(x<<|,k,val);
}
L query(int x,int l,int r){
if(l<=aa[x].l&&aa[x].r<=r) return aa[x].maxn;
L res=;
if(l<=mid) res=max(res,query(x<<,l,r));
if(mid<r) res=max(res,query(x<<|,l,r));
return res;
}
bool cmp(ask A,ask B){
int vala=A.isa?a[A.id].r:b[A.id].r;
int valb=B.isa?a[B.id].r:b[B.id].r;
if(vala!=valb) return vala<valb;
return A.isa<B.isa;
}
void sub(){
build(,,up);
N=; for(int i=;i<=n;i++) p[++N]=ask(i,),p[++N]=ask(i,);
sort(p+,p+N+,cmp);
for(int i=;i<=N;i++){
int id=p[i].id;
if(p[i].isa){
L now=query(,a[id].l,a[id].r);
ans=max(ans,now*a[id].val);
}else{
L val=1LL*b[id].val*(b[id].r-b[id].l+);
updata(,b[id].l,val);
}
}
}
void solve(){sub();swapAB();sub();swapAB();}
} void ReadData(){
cin>>n;
for(int i=;i<=n;i++) a[i].rd();
for(int i=;i<=n;i++) b[i].rd();
} struct line{
L k,b; line(){k=b=;}
line(L _k,L _b){b=_b; k=_k;}
L f(L x){return k*x+b;}
friend bool operator <(line a,line b){
if(a.k==b.k) return a.b<b.b;
return a.k<b.k;
}
friend double operator *(line a,line b){
return .*(b.b-a.b)/(a.k-b.k);
}
};
bool under(line a,line b,line c){
double x=a*b;
if(a.f(x)>=c.f(x)) return ;
return ;
}
struct plane{//半平面
set<line> s;
map<double,line> mp;
void clear(){
s.clear(); mp.clear();
s.insert(line(,));
mp[-]=line(,);
}
L f(int x){
map<double,line>::iterator it=mp.upper_bound(x); it--;
line now=it->second;
return now.f(x);
}
void remove(S it){
S nxt=it,pre=it; nxt++; pre--;
if(nxt!=s.end()){
double l=(*it)*(*nxt);
mp.erase(mp.find(l));
double x=(*nxt)*(*pre);
mp[x]=*nxt;
}
double r=(*it)*(*pre);
mp.erase(mp.find(r));
s.erase(it);
}
void insert(line l){
S nxt=s.upper_bound(l),pre=nxt; pre--;
if(nxt!=s.end()){
double x=(*nxt)*(*pre);
mp.erase(mp.find(x));
double r=l*(*nxt);
mp[r]=(*nxt);
}
double x=l*(*pre);
s.insert(l); mp[x]=l;
}
void add(line l){
S it=s.upper_bound(l),nx=it,ls=it,hh; ls--;
if(it!=s.end()&&under(*it,*ls,l)) return;
for(nx++;it!=s.end()&&nx!=s.end();it=nx,nx++){
double x=(*it)*(*nx);
line now=*it;
if(now.k==l.k) return;
if(l.f(x)>=now.f(x)) remove(it);
else break;
}
it=s.upper_bound(l); it--; ls=it;
for(ls--;it!=s.begin();){
double x=(*it)*(*ls);
line now=(*it);
if(now.k==l.k||l.f(x)>=now.f(x)){
hh=it; hh--; ls--;
remove(it);
it=hh;
}
else break;
}
insert(l);
}
}; namespace seg{
struct hhh{
int l,r; plane p;
void insert(line now){return p.add(now);}
L f(L x){return p.f(x);}
}aa[<<]; void build(int x,int l,int r){
aa[x].l=l; aa[x].r=r; aa[x].p.clear();
if(l==r) return;
build(x<<,l,mid); build(x<<|,mid+,r);
}
void updata(int x,int l,int r,line now){
if(l<=aa[x].l&&aa[x].r<=r) return aa[x].insert(now);
if(l<=mid) updata(x<<,l,r,now);
if(mid<r) updata(x<<|,l,r,now);
}
L query(int x,int k){
L res=aa[x].f(k);
if(aa[x].l==aa[x].r) return res;
if(k<=mid) res=max(res,query(x<<,k));
else res=max(res,query(x<<|,k));
return res;
}
} namespace SolveOthers{
void sub(){
seg::build(,,up);
N=; for(int i=;i<=n;i++) p[++N]=ask(i,),p[++N]=ask(i,);
sort(p+,p+N+);
for(int i=N;i;i--){
int id=p[i].id;
if(p[i].isa){
L now=seg::query(,a[id].r);
ans=max(ans,now*a[id].val);
}else{
line hh=line(b[id].val,-1LL*b[id].val*(b[id].l-));
seg::updata(,b[id].l,b[id].r,hh);
}
}
}
void solve(){sub();swapAB();sub();}
} main(){
ReadData();
SolveContains::solve();
SolveOthers::solve();
cout<<ans<<endl;
}

【xsy3423】党² 线段树+李超线段树or动态半平面交的更多相关文章

  1. 【BZOJ-4515】游戏 李超线段树 + 树链剖分 + 半平面交

    4515: [Sdoi2016]游戏 Time Limit: 40 Sec  Memory Limit: 256 MBSubmit: 304  Solved: 129[Submit][Status][ ...

  2. 【BZOJ-3165】Segment 李超线段树(标记永久化)

    3165: [Heoi2013]Segment Time Limit: 40 Sec  Memory Limit: 256 MBSubmit: 368  Solved: 148[Submit][Sta ...

  3. 【BZOJ-1568】Blue Mary开公司 李超线段树 (标记永久化)

    1568: [JSOI2008]Blue Mary开公司 Time Limit: 15 Sec  Memory Limit: 162 MBSubmit: 557  Solved: 192[Submit ...

  4. Codeforces Round #463 F. Escape Through Leaf (李超线段树合并)

    听说正解是啥 set启发式合并+维护凸包+二分 根本不会啊 , 只会 李超线段树合并 啦 ... 题意 给你一颗有 \(n\) 个点的树 , 每个节点有两个权值 \(a_i, b_i\) . 从 \( ...

  5. 【BZOJ3165】[HEOI2013]Segment(李超线段树)

    [BZOJ3165][HEOI2013]Segment(李超线段树) 题面 BZOJ 洛谷 题解 似乎还是模板题QwQ #include<iostream> #include<cst ...

  6. 【BZOJ1568】[JSOI2008]Blue Mary开公司(李超线段树)

    [BZOJ1568][JSOI2008]Blue Mary开公司(李超线段树) 题面 BZOJ 洛谷 题解 是模板题啊. #include<iostream> #include<cs ...

  7. Luogu P4097 [HEOI2013]Segment 李超线段树

    题目链接 \(Click\) \(Here\) 李超线段树的模板.但是因为我实在太\(Naive\)了,想象不到实现方法. 看代码就能懂的东西,放在这里用于复习. #include <bits/ ...

  8. BZOJ.3938.Robot(李超线段树)

    BZOJ UOJ 以时间\(t\)为横坐标,位置\(p\)为纵坐标建坐标系,那每个机器人就是一条\(0\sim INF\)的折线. 用李超线段树维护最大最小值.对于折线分成若干条线段依次插入即可. 最 ...

  9. BZOJ.4515.[SDOI2016]游戏(树链剖分 李超线段树)

    BZOJ 洛谷 每次在路径上加的数是个一次函数,容易看出是树剖+李超线段树维护函数最小值.所以其实依旧是模板题. 横坐标自然是取个确定的距离标准.取每个点到根节点的距离\(dis[i]\)作为\(i\ ...

随机推荐

  1. Find one unique integer

    https://github.com/Premiumlab/Python-for-Algorithms--Data-Structures--and-Interviews/blob/master/Moc ...

  2. IC向管理者角色转换

    1. 虽然你认为自己已经想明白怎么干,但还是从怎么干回归到要解决的问题,抛给正确的人(应该对这些问题负责的人),引导他们想出问题的答案. 给别人机会和空间,帮助他们成长: 人们对自己“想”出的方案更有 ...

  3. 2018.09.19 atcoder Snuke's Coloring(思维题)

    传送门 谁能想到这道题会写这么久. 本来是一道很sb的题啊. 就是每次选一个点只会影响到周围的九个方格,随便1e9进制就可以hash了,但是我非要作死用stl写. 结果由于技术不够高超,一直调不出来. ...

  4. Windows10和CentOS7双系统安装的一些小技巧

    我个人是先安装好了win10系统,且win10是单独在一个120g的盘里:而centOS7则是安装在另一个500g的磁盘的其中的380g里: 这里要着重注意的是,500g里分成380g的盘不要在win ...

  5. FIR IP

    (1)多通道系数处理 系数的格式 (1)       每组系数的长度必须一样长: (2)多组系数依次连接即可; 添加多组系数后会,FIR IP核在生成时会多出以下几个信号 .s_axis_config ...

  6. log4j日志文件路径设置

    假设有如下标准化的目录结构: $HOME |-- log |-- conf |-- bin |-- lib |-- data jar包放在lib目录,启动脚本放在bin目录,日志文件放在log目录,配 ...

  7. Tensorflow从源代码编译2

    https://blog.csdn.net/qq_37674858/article/details/81095101 https://blog.csdn.net/yhily2008/article/d ...

  8. springmvc 孔浩

    modelAttribute属性指定该form绑定的是哪个Model,当指定了对应的Model后就可以在form标签内部其 它表单标签上通过为path指定Model属性的名称来绑定Model中的数据了 ...

  9. How To Change the Supplier Bank Account Masking in UI (Doc ID 877074.1)

      Give Feedback...           How To Change the Supplier Bank Account Masking in UI (Doc ID 877074.1) ...

  10. [翻译]NUnit---Property and Random Attributes(十四)

    小记:由于工作琐碎,没得心情翻译而且也在看<CLR vis C#>,所以断更了差不多5个月,现在继续翻译,保证会翻译完成,不会虎头蛇尾. 另:NUnit已经更新到2.6.3版本,虽然正在开 ...