此题写得比较奇怪比较二逼。。。。
首先我们可以算出每个线段相对于出发点的出现时间(勉强听得懂吧。。。)
现在问题就变成给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;
}