首先把區間一段一段分出來,那麼只有四種狀況。
要麼沒有被任何一朵雲被覆蓋,那麼直接就會產生這一段的貢獻。
要麼被一朵雲覆蓋,要麼被兩朵雲覆蓋。
要麼被三朵及以上的雲所覆蓋,那麼這段的貢獻永遠取不到。spa
對於每朵雲預處理出只被其覆蓋的區間長度\(len[i]\),這樣子就能處理只選擇一朵雲的貢獻了。
如今考慮如何處理選擇兩朵雲。
這裏有兩種狀況。
第一種是兩朵雲無交,那麼貢獻就是\(len[i]+len[j]\)。
不然的話有交,而且交的部分只被這兩朵雲所覆蓋,不能發現這樣子的狀況不會超過\(n\)個,這個東西能夠拿出來暴力更新。
這樣子咱們能夠預處理一個前綴的值,表明在這個位置以前選擇雲可以獲得的最大空出來的時間。code
對於第一種狀況,能夠按照價格大小構建一棵線段樹,這樣子每次就是區間查最大值。
對於第二種狀況,找到這個區間而後把兩個的貢獻算在一塊兒就行了。get
#include<iostream> #include<cstdio> #include<algorithm> #include<set> #include<map> using namespace std; #define MAX 300300 inline int read() { int x=0;bool t=false;char ch=getchar(); while((ch<'0'||ch>'9')&&ch!='-')ch=getchar(); if(ch=='-')t=true,ch=getchar(); while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar(); return t?-x:x; } struct Cloud{int l,r,c;}c[MAX]; bool operator<(Cloud a,Cloud b){return a.c<b.c;} struct Node{int t,opt,id;}a[MAX<<1]; bool operator<(Node a,Node b){return a.t<b.t;} struct Qry{int k,id;}q[MAX]; bool operator<(Qry a,Qry b){return a.k<b.k;} int n,m,C,cnt,ans[MAX],len[MAX],cho[MAX]; namespace SegmentTree { #define lson (now<<1) #define rson (now<<1|1) int t[MAX<<2]; void Modify(int now,int l,int r,int p,int w) { if(l==r){t[now]=w;return;} int mid=(l+r)>>1; if(p<=mid)Modify(lson,l,mid,p,w); else Modify(rson,mid+1,r,p,w); t[now]=max(t[lson],t[rson]); } int Getmax(int now,int l,int r) { if(l==r)return l; int mid=(l+r)>>1; if(t[lson]>t[rson])return Getmax(lson,l,mid); else return Getmax(rson,mid+1,r); } int Query(int now,int l,int r,int L,int R) { if(L<=l&&r<=R)return Getmax(now,l,r); int mid=(l+r)>>1,ret=0; if(L<=mid)ret=Query(lson,l,mid,L,R); if(R>mid) { int x=Query(rson,mid+1,r,L,R); if(len[x]>len[ret])ret=x; } return ret; } } using namespace SegmentTree; set<int> S; map<int,int> M[MAX]; int Calc(int i,int j){if(i>j)swap(i,j);return len[i]+len[j]+M[i][j];} int main() { n=read();C=read(); for(int i=1;i<=n;++i)c[i].l=read(),c[i].r=read(),c[i].c=read(); sort(&c[1],&c[n+1]);c[n+1]=(Cloud){0,0,2000000000}; for(int i=1;i<=n;++i)a[++cnt]=(Node){c[i].l,1,i},a[++cnt]=(Node){c[i].r,-1,i}; sort(&a[1],&a[cnt+1]);a[++cnt]=(Node){2000000010,1,n+1}; m=read();for(int i=1;i<=m;++i)q[i].k=read(),q[i].id=i; sort(&q[1],&q[m+1]); int Sum=0,Del=0; for(int i=1,tim=0,pos=1;i<=cnt;++i) { int l=a[i].t-tim;tim=a[i].t; if(!S.size())Sum+=l; else if(S.size()==1) { int x=*S.begin(); len[x]+=l;cho[x]+=l;Modify(1,1,n,x,len[x]); if(c[x].c<=C) { int l=1,r=upper_bound(&c[1],&c[n+1],(Cloud){0,0,C-c[x].c})-c-1,val=len[x]; if(l<=x&&x<=r) { if(l<=x-1)val=max(val,Calc(x,Query(1,1,n,l,x-1))); if(x+1<=r)val=max(val,Calc(x,Query(1,1,n,x+1,r))); } else if(l<=r)val=max(val,Calc(x,Query(1,1,n,l,r))); cho[x]=max(cho[x],val); Del=max(Del,cho[x]); } } else if(S.size()==2) { int x=*S.begin(),y=*S.rbegin();M[x][y]+=l; if(c[x].c+c[y].c<=C) { cho[x]=max(cho[x],Calc(x,y)); cho[y]=max(cho[y],Calc(x,y)); Del=max(Del,max(cho[x],cho[y])); } } while(pos<=m&&Del+Sum>=q[pos].k)ans[q[pos].id]=tim-(Del+Sum-q[pos].k),++pos; if(a[i].opt==1)S.insert(a[i].id); else S.erase(a[i].id); } for(int i=1;i<=m;++i)printf("%d\n",ans[i]); return 0; }