noip模拟37 数对

裸的线段树,这里不再讲方程的转移实现,主要证明一下按照和排序的正确性。
noip模拟37 数对

对于 \(j\) 我们希望 \(i\) 再其的前面。格式化的,对于 \(a_{i}\leq b_{j}\) 且 \(b_{i}\leq a_{j}\) ,我们期望 \(i\) 排在 \(j\) 的前面。
为什么要 \(b_{i}\) 小于 \(a_{j}\) 呢?
(其实是当其满足大于时, \(i\) 和 \(j\) 的顺序对答案没有影响。)
然后显然的按从小到大排序就好了。

code:

#include <bits/stdc++.h>
#define re register
#define int long long
using namespace std; 
const int maxn=200010;
const int INF=1e18;
char buf[1<<21], *p1=buf, *p2=buf;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf, 1, 1<<21, stdin)), p1==p2?EOF:*p1++)
inline int read() {
    int s=0,w=1; char ch=getchar();
    while(ch<'0'||ch>'9') { if(ch=='-') w=-1;ch=getchar(); }
    while(ch>='0'&&ch<='9') { s=s*10+ch-'0'; ch=getchar(); }
    return s*w; 
} 
struct DATE { int a,b,w; int val(){return a+b;} } dat[maxn];
inline bool cmp(DATE as,DATE bs) { return as.val()<bs.val(); }
int n,tot,s[maxn];
#define lid (id<<1)
#define rid (id<<1|1)
struct TREE { int pos,maxl,lazy; } tre[maxn<<2];
inline TREE mx(TREE a,TREE b) { return (a.maxl>=b.maxl)? a:b; }
inline void update(int id) { tre[id]=mx(tre[lid],tre[rid]); }
inline void push_down(int id) {
	int s=tre[id].lazy; tre[id].lazy=0;
	tre[lid].maxl+=s; tre[rid].maxl+=s;
	tre[lid].lazy+=s; tre[rid].lazy+=s;
}
inline TREE query(int id,int l,int r,int ll,int rr) {
	if(ll==rr) { if(ll==1) { if(tre[id].lazy) cout<<" wrong "<<endl; } }
	if(tre[id].lazy&&l!=r) push_down(id);
	if(ll<=l&&r<=rr) { return tre[id]; } 
	int mid=(l+r)>>1; TREE ans=(TREE){0,0,0}; 
	if(ll<=mid) ans=mx(ans,query(lid,l,mid,ll,rr));
	if(rr>mid) ans=mx(ans,query(rid,mid+1,r,ll,rr));
	return ans;
}
inline void add(int id,int l,int r,int pos,int val) {
	if(tre[id].lazy&&l!=r) push_down(id);
	if(l==r) { tre[id].maxl=max(tre[id].maxl,val); return; }
	int mid=(l+r)>>1;
	if(pos<=mid) add(lid,l,mid,pos,val);
	else if(pos>mid) add(rid,mid+1,r,pos,val);
	update(id);tre[id].lazy=0;
}
inline void insert(int id,int l,int r,int ll,int rr,int val) {
	if(tre[id].lazy&&l!=r) push_down(id);
	if(ll<=l&&r<=rr) { tre[id].maxl+=val; tre[id].lazy+=val; return; }
	int mid=(l+r)>>1; 
	if(ll<=mid) insert(lid,l,mid,ll,rr,val);
	if(rr>mid) insert(rid,mid+1,r,ll,rr,val);
	update(id);tre[id].lazy=0;
}
inline void build(int id,int l,int r) {
	if(l==r) { tre[id]=(TREE){l,0,0}; return; }
	int mid=(l+r)>>1;
	build(lid,l,mid); build(rid,mid+1,r); 
	update(id); tre[id].lazy=0;
}
signed main(void) {
	//freopen("pair.in","r",stdin);
	//freopen("cs.txt","w",stdout);
	n=read();
	for(re int i=1;i<=n;i++) { 
		dat[i].a=read(); dat[i].b=read(); dat[i].w=read();
		s[++tot]=dat[i].a; s[++tot]=dat[i].b; 
	}
	sort(s+1,s+1+tot); 
	tot=unique(s+1,s+1+tot)-s-1; 	
	for(re int i=1;i<=n;i++) { 
		dat[i].a=lower_bound(s+1,s+1+tot,dat[i].a)-s;
		dat[i].b=lower_bound(s+1,s+1+tot,dat[i].b)-s;
	}
	sort(dat+1,dat+1+n,cmp); build(1,1,tot); 
	for(re int i=1;i<=n;i++) {
		TREE res=(TREE){0,0,0}; 
		if(dat[i].a<=dat[i].b) {
			res=query(1,1,tot,1,dat[i].a); 
			add(1,1,tot,dat[i].a,res.maxl+dat[i].w); 
			res=(TREE){0,0,0}; 
			if(dat[i].a+1<=dat[i].b) {
				insert(1,1,tot,dat[i].a+1,dat[i].b,dat[i].w);
			}
		}
		else {
			res=query(1,1,tot,1,dat[i].b); 
			add(1,1,tot,dat[i].a,res.maxl+dat[i].w); 
		}
	}
	printf("%lld\n",tre[1].maxl); 
}

上一篇:React入门教程


下一篇:HCIP (华为高级网络安全工程师)(第五天)(OSPF协议)