# 【题解】Subsequence [SWTR-05] [P]

## 【Code】

#include<algorithm>
#include<iostream>
#include<cstdio>
#include<queue>
#define LL unsigned int
#define Re register LL
using namespace std;
const int N=2e5+10;
LL n,T,A[N],S[N],S1[N],S2[N],Ans[N];
struct QAQ{LL v,l,r,id;inline bool operator<(const QAQ &O)const{return v>O.v;}}a[N],Q[N];
inline void in(Re &x){
int f=0;x=0;char c=getchar();
while(c<'0'||c>'9')f|=c=='-',c=getchar();
while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+(c^48),c=getchar();
x=f?-x:x;
}
inline void print(Re x){if(x>9)print(x/10);putchar(x%10+'0');}
inline LL ask1(Re l,Re r){return l<=r&&r>=1?S1[r]-(l?S1[l-1]:0):0;}
inline LL ask2(Re l,Re r){return l<=r&&r>=1?S2[r]-(l?S2[l-1]:0):0;}
struct Splay{
#define pl (tr[p].ps[0])
#define pr (tr[p].ps[1])
#define pf (tr[p].fa)
#define pv (tr[p].v)
LL O,root,Q[N];queue<LL>D;
struct QAQ{LL l,r,v,S,rr,fa,size,ps[2];}tr[N];
inline void pushup(Re p){
tr[p].S=tr[pl].S+tr[pr].S+pv;
tr[p].rr=pr?tr[pr].rr:tr[p].r;
tr[p].size=tr[pl].size+tr[pr].size+1;
}
inline LL which(Re p){return tr[pf].ps[1]==p;}
inline void connect(Re p,Re fa,Re o){tr[pf=fa].ps[o]=p;}
inline void rotate(Re p){
Re fa=pf,fas=which(p);
Re pa=tr[fa].fa,pas=which(fa);
Re x=tr[p].ps[fas^1];
connect(x,fa,fas),connect(fa,p,fas^1),connect(p,pa,pas);
pushup(fa),pushup(p);
}
inline void splay(Re p,Re to){
for(Re fa;pf!=to;rotate(p))
if(tr[fa=pf].fa!=to)rotate(which(p)==which(fa)?fa:p);
if(!to)root=p;
}
inline void CL(Re p){
tr[p].size=tr[p].S=tr[p].l=tr[p].r=tr[p].rr=pv=pf=pl=pr=0;
}
inline LL New(){
Re p;
if(D.empty())p=++O;
else p=D.front(),D.pop();
CL(p),tr[p].size=1;return p;
}
inline void build0(Re &p,Re l,Re r){//建初始区间{1,n}时在下面挂一个{0,0}和{n+1,n+1}，方便后面split
p=New(),tr[p].l=l,tr[p].r=r,pv=calc(l,r);
pl=New(),tr[pl].l=tr[pl].r=0,tr[pl].v=0,tr[pl].fa=p,pushup(pl);
pr=New(),tr[pr].l=tr[pr].r=n+1,tr[pr].v=0,tr[pr].fa=p,pushup(pr);
pushup(p);
}
inline void build(Re &p,Re l,Re r){
p=New(),tr[p].l=l,tr[p].r=r,pv=calc(l,r),pushup(p);
}
inline LL find(Re p,Re K){
if(K<=tr[pl].size)return find(pl,K);
return K<=tr[pl].size+1?p:find(pr,K-tr[pl].size-1);
}
inline LL split(Re L,Re R){//在Spaly维护的序列上获取区间[L,R]
Re p=find(root,L-1),q=find(root,R+1);
splay(p,0),splay(q,p);return tr[q].ps[0];
}
inline void insert(Re st,Re l,Re r){//在Spaly维护的序列上第st个点后插入节点{l,r,calc(l,r)}
Re rt=0;build(rt,l,r);
Re p=find(root,st),q=find(root,st+1);
splay(p,0),splay(q,p);
connect(rt,q,0),pushup(q),pushup(p);
}
inline void erase(Re pos){//删除Spaly维护的序列上第pos个节点
Re p=split(pos,pos),fa=pf;
tr[fa].ps[0]=pf=0,D.push(p),CL(p);
pushup(fa),pushup(tr[fa].fa);
}
inline LL ask(Re L,Re R){return L<=R?tr[split(L,R)].S:0;}
inline LL getpos(Re p,Re x){//寻找x所在连续段在Splay上的编号，如果找不到就返回其后面第一个连续段
if(x<tr[p].l)return x<=tr[pl].rr?getpos(pl,x):p;
return (x>=tr[p].l&&x<=tr[p].r)?p:getpos(pr,x);
}
}T1;
struct QWQ{LL l,r,p,pos;};
inline QWQ get(Re x){
QWQ a;a.p=T1.getpos(T1.root,x),T1.splay(a.p,0);
a.l=T1.tr[a.p].l,a.r=T1.tr[a.p].r,a.pos=T1.tr[T1.tr[a.p].ps[0]].size+1;
return a;
}
QWQ a=get(x);
T1.erase(a.pos),--a.pos;
if(a.l<x)T1.insert(a.pos,a.l,x-1),++a.pos;
if(x<a.r)T1.insert(a.pos,x+1,a.r);
}
inline void updata(QWQ &a){
a.p=T1.find(T1.root,a.pos),a.l=T1.tr[a.p].l,a.r=T1.tr[a.p].r;
}
if(T1.tr[T1.root].size==2)return 0;//没有连续段了
QWQ bl=get(L),br=get(R);LL ans=0;
if(R<br.l)--br.pos,updata(br);//如果返回了R后面第一个连续段，稍微处理下
Re flag1=(L>=bl.l&&L<=bl.r),flag2=(R>=br.l&&R<=br.r);//flag1,flag2分别表示左右端点是否在连续段中间
if(flag1&&flag2&&bl.pos==br.pos)return calc(L,R);//同一连续段
if(flag1)ans+=calc(L,bl.r),++bl.pos,updata(bl);//左端点所在连续段被割断
if(flag2)ans+=calc(br.l,R),--br.pos,updata(br);//右端点所在连续段被割断
return ans;
}
int main(){
//    freopen("123.txt","r",stdin);
in(n),in(T);
for(Re i=1;i<=n;++i)in(A[i]),S[i]=S[i-1]+A[i],S1[i]=S1[i-1]+S[i]*i,S2[i]=S2[i-1]+S[i],a[i].v=A[i],a[i].id=i;
for(Re i=1;i<=T;++i)in(Q[i].l),in(Q[i].r),in(Q[i].v),Q[i].id=i;
sort(a+1,a+n+1),sort(Q+1,Q+T+1);
T1.build0(T1.root,1,n);
for(Re i=1,j=0;i<=T;++i){