这原本是历史遗留问题,属于一直没补的题,许久前看到这题要用cdq就放着了,看了cdq之后写了两种写法,都挂了,(到现在都不能说完全理解了cdq)遂放弃cdq写法。
后来换了树状数组,但是因为离散化方向的问题,没打出来,因为不想倒着离散化。最后写了线段树,总算有了跟19不一样的分数,WA#3#4两个点,看一篇cdq题解里面提到的端点重合问题,貌似这种写法是没有的,求教
#include<bits/stdc++.h>
using namespace std;
int n,m,bonus[300005],tot,uni[300005],N,ans[300005];
struct node{
int u,v,id,to;
}c[300005];
bool _(node u,node v){
return u.u<v.u;
}
struct Seg{
int l,r,mx;
#define l(o) C[o].l
#define r(o) C[o].r
#define mx(o) C[o].mx
#define mid(o) ((C[o].l+C[o].r)/2)
}C[1200005];
void build(int o,int l,int r){
l(o)=l;
r(o)=r;
if(l>=r){
mx(o)=0;
return;
}
build(o*2,l,mid(o));
build(o*2+1,mid(o)+1,r);
}
void update(int o,int x,int v){
if(l(o)==x&&r(o)==x){
mx(o)=max(mx(o),v);
return;
}
if(x<=mid(o))
update(o*2,x,v);
else update(o*2+1,x,v);
mx(o)=max(mx(o*2),mx(o*2+1));
}
int query(int o,int l,int r){
if(l(o)>=l&&r(o)<=r)
return mx(o);
int res=0;
if(l<=mid(o))
res=max(res,query(o*2,l,r));
if(r>mid(o))
res=max(res,query(o*2+1,l,r));
return res;
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin>>n>>m;
tot++;
c[tot]={0,0,tot,0};
uni[++N]=0;
tot++;
c[tot]={n,n,tot,0};
uni[++N]=n;
for(int i=1,u1,v1,u2,v2;i<=m;i++){
cin>>u1>>v1>>u2>>v2;
tot++;
c[tot]={u1,v1,tot,tot+1};
uni[++N]=v1;
bonus[tot]=u2-u1+v2-v1;
tot++;
c[tot]={u2,v2,tot,0};
uni[++N]=v2;
}
sort(uni+1,uni+N+1);
N=unique(uni+1,uni+N+1)-uni-1;
build(1,1,N);
sort(c+1,c+tot+1,_);
for(int i=1;i<=tot;i++){
c[i].v=lower_bound(uni+1,uni+N+1,c[i].v)-uni;
ans[c[i].id]=max(query(1,1,c[i].v),ans[c[i].id]);
update(1,c[i].v,ans[c[i].id]);
if(bonus[c[i].id])
ans[c[i].to]=max(ans[c[i].to],ans[c[i].id]+bonus[c[i].id]);
}
cout<<n*2-ans[2];
}/*
*/