此题写得比较奇怪比较二逼。。。。
首先我们可以算出每个线段相对于出发点的出现时间(勉强听得懂吧。。。)
现在问题就变成给n条已知线段,询问射线[n,+oo)中线段的总长度。
基础的主席树啦。。。。
(好吧,似乎有跟好的算法。。)
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef long long LL; const int Maxn=2000005, Maxm=100005; int minx[Maxn],tip[Maxn],a[Maxn]; int L[Maxm],R[Maxm],ti[Maxm],T[Maxm*2]; int lef[Maxn*2],rig[Maxn*2],b[Maxn],c[Maxn]; int n,m,N,M,t,i,j,x,y,start; LL sum1[Maxn*2],sum2[Maxn*2],f[Maxm*2],ans; struct arr { int l,r; bool operator <(const arr &a)const { return (r<a.r || (r==a.r && l<a.l)); } } G[Maxn]; void push(int p){ if (tip[p*2+1]>tip[p] || tip[p*2+1]<0) tip[p*2+1]=tip[p]; if (tip[p*2+2]>tip[p] || tip[p*2+2]<0) tip[p*2+2]=tip[p]; minx[p*2+1]=min(minx[p*2+1],tip[p]); minx[p*2+2]=min(minx[p*2+2],tip[p]); tip[p]=-1; } void add(int p,int l,int r,int L,int R,int data){ if (l>R || L>r) return; if (L<=l && R>=r){ if (tip[p]>data || tip[p]<0) tip[p]=data; minx[p]=min(minx[p],data); return; } if (tip[p]>=0) push(p); int mid=(l+r)>>1; add(p*2+1,l,mid,L,R,data); add(p*2+2,mid+1,r,L,R,data); minx[p]=min(minx[p*2+1],minx[p*2+2]); } void getit(int p,int l,int r){ if (l==r){ c[l]=minx[p]; return; } if (tip[p]>=0) push(p); int mid=(l+r)>>1; getit(p*2+1,l,mid); getit(p*2+2,mid+1,r); } void work1(){ for (i=1;i<=m;i++){ scanf("%d%d%d",&L[i],&R[i],&ti[i]); R[i]--; a[++M]=L[i]-1; a[++M]=L[i]; a[++M]=R[i]; a[++M]=R[i]+1; } sort(a+1,a+M+1); M=unique(a+1,a+M+1)-a-1; memset(minx,127/2,sizeof(minx)); memset(tip,-1,sizeof(tip)); for (i=1;i<=m;i++){ L[i]=lower_bound(a+1,a+M+1,L[i])-a; R[i]=lower_bound(a+1,a+M+1,R[i])-a; add(0,1,M,L[i],R[i],ti[i]); } getit(0,1,M); for (i=1,N=t=0;i<=M;i=j){ for (j=i;c[j]==c[i]&&j<=M;j++); if (c[i]>1000000000) continue; G[++N].r=c[i]-a[i]; G[N].l=c[j-1]-a[j-1]; b[++t]=G[N].l; } } void ins(int p,int &q,int l,int r,int x){ q=++start; lef[q]=lef[p]; rig[q]=rig[p]; sum1[q]=sum1[p]+(LL)b[G[x].l]-1; sum2[q]=sum2[p]+1; if (l==r) return; int mid=(l+r)>>1; if (G[x].l<=mid) ins(lef[p],lef[q],l,mid,x); else ins(rig[p],rig[q],mid+1,r,x); } void query(int p,int l,int r,int x){ if (b[l]>x || p==0) return; if (b[r]<=x){ ans+=sum2[p]*(LL)x-sum1[p]; return; } int mid=(l+r)>>1; query(lef[p],l,mid,x); query(rig[p],mid+1,r,x); } int UPPER_BOUND(int x){ int l=1, r=N; int mid, ret=0; while (l<=r){ mid=(l+r)>>1; if (G[mid].r<=x) ret=mid, l=mid+1; else r=mid-1; } return ret; } void work2(){ sort(G+1,G+N+1); for (i=1;i<=N;i++) f[i]=f[i-1]+(LL)(G[i].r-G[i].l+1); sort(b+1,b+t+1); t=unique(b+1,b+t+1)-b-1; for (i=N;i>0;i--){ G[i].l=lower_bound(b+1,b+t+1,G[i].l)-b; ins(T[i+1],T[i],1,t,i); } for (i=1;i<=n;i++){ scanf("%d",&x); y=UPPER_BOUND(x); ans=f[y++]; query(T[y],1,t,x); printf("%I64d\n",ans); } } int main(){ //freopen("286D.in","r",stdin); //freopen("286D.out","w",stdout); scanf("%d%d",&n,&m); work1(); work2(); return 0; }