noip模擬37 數對
阿新 • • 發佈:2021-08-12
裸的線段樹,這裡不再講方程的轉移實現,主要證明一下按照和排序的正確性。
對於 \(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); }