题面
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/3b79af1f8a14d572f20889e313a3a11e.png)
题解
- 很妙的线段树维护
d
p
dp
dp的题
- 首先需要明确的是需要怎样将其划分为两个满足条件的集合,根据题意,可以知道可以用一个台阶将集合划分,如图
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/d53f07cc05e3fe071b9d808c50d2b44b.png)
- 然后就可以将每个点的
y
y
y进行离散化,然后考虑将这些点优先按照
x
x
x升序,然后
y
y
y升序的规则排序,显然每经过一个点,它所带来的贡献需要修改的是一个区间,所以考虑线段树维护区间最大值,然后进行状态转移
- 转移的过程很妙,代码语言能更好说明~~~
#include<bits/stdc++.h>
using namespace std;
namespace IO{
#define BUF_SIZE 100000
#define OUT_SIZE 100000
#define ll long long
bool IOerror=0;
inline char nc(){
static char buf[BUF_SIZE],*p1=buf+BUF_SIZE,*pend=buf+BUF_SIZE;
if (p1==pend){
p1=buf; pend=buf+fread(buf,1,BUF_SIZE,stdin);
if (pend==p1){IOerror=1;return -1;}
}
return *p1++;
}
inline bool blank(char ch){return ch==' '||ch=='\n'||ch=='\r'||ch=='\t';}
inline bool read(int &x){
bool sign=0; char ch=nc(); x=0;
for (;blank(ch);ch=nc());
if (IOerror)return false;
if (ch=='-')sign=1,ch=nc();
for (;ch>='0'&&ch<='9';ch=nc())x=x*10+ch-'0';
if (sign)x=-x; return true;
}
inline void read(ll &x){
bool sign=0; char ch=nc(); x=0;
for (;blank(ch);ch=nc());
if (IOerror)return;
if (ch=='-')sign=1,ch=nc();
for (;ch>='0'&&ch<='9';ch=nc())x=x*10+ch-'0';
if (sign)x=-x;
}
inline void read(double &x){
bool sign=0; char ch=nc(); x=0;
for (;blank(ch);ch=nc());
if (IOerror)return;
if (ch=='-')sign=1,ch=nc();
for (;ch>='0'&&ch<='9';ch=nc())x=x*10+ch-'0';
if (ch=='.'){
double tmp=1; ch=nc();
for (;ch>='0'&&ch<='9';ch=nc())tmp/=10.0,x+=tmp*(ch-'0');
}
if (sign)x=-x;
}
inline void read(char *s){
char ch=nc();
for (;blank(ch);ch=nc());
if (IOerror)return;
for (;!blank(ch)&&!IOerror;ch=nc())*s++=ch;
*s=0;
}
inline void read(char &c){
for (c=nc();blank(c);c=nc());
if (IOerror){c=-1;return;}
}
struct Ostream_fwrite{
char *buf,*p1,*pend;
Ostream_fwrite(){buf=new char[BUF_SIZE];p1=buf;pend=buf+BUF_SIZE;}
void out(char ch){
if (p1==pend){
fwrite(buf,1,BUF_SIZE,stdout);p1=buf;
}
*p1++=ch;
}
void print(int x){
static char s[15],*s1;s1=s;
if (!x)*s1++='0';if (x<0)out('-'),x=-x;
while(x)*s1++=x%10+'0',x/=10;
while(s1--!=s)out(*s1);
}
void println(int x){
static char s[15],*s1;s1=s;
if (!x)*s1++='0';if (x<0)out('-'),x=-x;
while(x)*s1++=x%10+'0',x/=10;
while(s1--!=s)out(*s1); out('\n');
}
void print(ll x){
static char s[25],*s1;s1=s;
if (!x)*s1++='0';if (x<0)out('-'),x=-x;
while(x)*s1++=x%10+'0',x/=10;
while(s1--!=s)out(*s1);
}
void println(ll x){
static char s[25],*s1;s1=s;
if (!x)*s1++='0';if (x<0)out('-'),x=-x;
while(x)*s1++=x%10+'0',x/=10;
while(s1--!=s)out(*s1); out('\n');
}
void print(double x,int y){
static ll mul[]={1,10,100,1000,10000,100000,1000000,10000000,100000000,
1000000000,10000000000LL,100000000000LL,1000000000000LL,10000000000000LL,
100000000000000LL,1000000000000000LL,10000000000000000LL,100000000000000000LL};
if (x<-1e-12)out('-'),x=-x;x*=mul[y];
ll x1=(ll)floor(x); if (x-floor(x)>=0.5)++x1;
ll x2=x1/mul[y],x3=x1-x2*mul[y]; print(x2);
if (y>0){out('.'); for (size_t i=1;i<y&&x3*mul[i]<mul[y];out('0'),++i) {}; print(x3);}
}
void println(double x,int y){print(x,y);out('\n');}
void print(char *s){while (*s)out(*s++);}
void println(char *s){while (*s)out(*s++);out('\n');}
void flush(){if (p1!=buf){fwrite(buf,1,p1-buf,stdout);p1=buf;}}
~Ostream_fwrite(){flush();}
}Ostream;
inline void print(int x){Ostream.print(x);}
inline void println(int x){Ostream.println(x);}
inline void print(char x){Ostream.out(x);}
inline void println(char x){Ostream.out(x);Ostream.out('\n');}
inline void print(ll x){Ostream.print(x);}
inline void println(ll x){Ostream.println(x);}
inline void print(double x,int y){Ostream.print(x,y);}
inline void println(double x,int y){Ostream.println(x,y);}
inline void print(char *s){Ostream.print(s);}
inline void println(char *s){Ostream.println(s);}
inline void println(){Ostream.out('\n');}
inline void flush(){Ostream.flush();}
#undef ll
#undef OUT_SIZE
#undef BUF_SIZE
};
using namespace IO;
const int maxn=1e5+10;
struct node{
int l,r;
long long mark,maxx;
node(int a=0,int b=0,long long c=0,long long d=0) {
l=a;r=b;mark=c;maxx=d;
}
}tree[maxn<<2];
void build(int id,int le,int ri)
{
tree[id]=node(le,ri,0,0);
if(le==ri) return;
int mid=(le+ri)>>1;
build(id<<1,le,mid);build(id<<1|1,mid+1,ri);
}
void pushup(int id)
{
tree[id].maxx=max(tree[id<<1].maxx,tree[id<<1|1].maxx);
}
void down(int id)
{
tree[id<<1].maxx+=tree[id].mark;
tree[id<<1|1].maxx+=tree[id].mark;
tree[id<<1].mark+=tree[id].mark;
tree[id<<1|1].mark+=tree[id].mark;
tree[id].mark=0;
}
void change(int id,int pos,long long val)
{
if(tree[id].l==tree[id].r) {tree[id].maxx=val;return;}
if(tree[id].mark) down(id);
int mid=(tree[id].l+tree[id].r)>>1;
if(pos<=mid) change(id<<1,pos,val);
else change(id<<1|1,pos,val);
pushup(id);
}
void update(int id,int le,int ri,int add)
{
if(tree[id].l>=le&&tree[id].r<=ri) {
tree[id].mark+=add;
tree[id].maxx+=add;
return;
}
if(tree[id].mark) down(id);
int mid=(tree[id].l+tree[id].r)>>1;
if(le>mid) update(id<<1|1,le,ri,add);
else if(ri<=mid) update(id<<1,le,ri,add);
else update(id<<1,le,mid,add),update(id<<1|1,mid+1,ri,add);
pushup(id);
}
long long query(int id,int le,int ri)
{
long long res=0;
if(tree[id].l>=le&&tree[id].r<=ri) return tree[id].maxx;
if(tree[id].mark) down(id);
int mid=(tree[id].l+tree[id].r)>>1;
if(le>mid) res=max(res,query(id<<1|1,le,ri));
else if(ri<=mid) res=max(res,query(id<<1,le,ri));
else res=max(res,max(query(id<<1,le,mid),query(id<<1|1,mid+1,ri)));
pushup(id);return res;
}
struct point{
int x,y;long long a,b;
point(int c=0,int d=0,long long e=0,long long f=0){
x=c;y=d;a=e;b=f;
}
friend bool operator<(const point &a,const point &b){
return a.x==b.x?a.y>b.y:a.x<b.x;
}
}p[maxn];
int n;long long h[maxn];
int main()
{
while(read(n)) {
for(int i=1;i<=n;i++) read(p[i].x),read(p[i].y),read(p[i].a),read(p[i].b),h[i]=p[i].y;
h[n+1]=0;sort(h+1,h+n+2);int tot=unique(h+1,h+n+2)-h-1;build(1,1,tot);
for(int i=1;i<=n;i++) p[i].y=lower_bound(h+1,h+tot+1,p[i].y)-h;sort(p+1,p+n+1);
for(int i=1;i<=n;i++) {
if(p[i].y<tot) update(1,p[i].y+1,tot,p[i].b);
change(1,p[i].y,query(1,1,p[i].y)+p[i].b);
if(p[i].y>1) update(1,1,p[i].y-1,p[i].a);
}
printf("%lld\n",query(1,1,tot));
}
}