题解:
考虑最高木板,如果最终水位高于这个高度,那么全部都高于这个高度,枚举最终高度,用主席树快速查询贡献。
否则转化为子问题递归解决。
#include <bits/stdc++.h>
using namespace std;
typedef pair <int,int> pii;
const int RLEN=1<<18|1;
inline char nc() {
static char ibuf[RLEN],*ib,*ob;
(ib==ob) && (ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
return (ib==ob) ? -1 : *ib++;
}
inline int rd() {
char ch=nc(); int i=0,f=1;
while(!isdigit(ch)) {if(ch=='-')f=-1; ch=nc();}
while(isdigit(ch)) {i=(i<<1)+(i<<3)+ch-'0'; ch=nc();}
return i*f;
}
const int N=3e5+50, L=32;
const int INF=0x3f3f3f3f;
int n,m;
namespace PST {
int rt0[N],rt1[N],tot;
struct node {
int lc,rc,sze;
} tr[N*(L+5)];
inline int ask(int x,int y,int l,int r,int L,int R) {
if(!y || !(tr[y].sze-tr[x].sze)) return 0;
if(L<=l && r<=R) return tr[y].sze-tr[x].sze;
int mid=(l+r)>>1;
if(R<=mid) return ask(tr[x].lc,tr[y].lc,l,mid,L,R);
else if(L>mid) return ask(tr[x].rc,tr[y].rc,mid+1,r,L,R);
else return ask(tr[x].lc,tr[y].lc,l,mid,L,R)+ask(tr[x].rc,tr[y].rc,mid+1,r,L,R);
}
inline void inc(int x,int &y,int l,int r,int p) {
y=++tot; tr[y]=tr[x]; ++tr[y].sze; if(l==r) return;
int mid=(l+r)>>1; (p<=mid) ? inc(tr[x].lc,tr[y].lc,l,mid,p) : inc(tr[x].rc,tr[y].rc,mid+1,r,p);
}
inline void init(vector <pii> *lim) {
for(int i=1;i<=n;i++) {
rt0[i]=rt0[i-1];
rt1[i]=rt1[i-1];
for(auto j:lim[i]) {
if(j.second) inc(rt1[i],rt1[i],0,INF,j.first);
else inc(rt0[i],rt0[i],0,INF,j.first);
}
}
}
inline int ask(int l,int r,int v,int rs=0) {
rs+=ask(rt0[l-1],rt0[r],0,INF,v,INF+1);
if(v) rs+=ask(rt1[l-1],rt1[r],0,INF,0,v-1);
return rs;
}
}
struct node {
int l,r,h;
node(int l=0,int r=0,int h=0) : l(l),r(r),h(h) {}
friend inline bool operator <(const node &a,const node &b) {return a.h<b.h;}
} tr[N];
int li[N],pl[N],pr[N],ri[N],hi[N],ti[N],idx; pii st[N]; int tl;
map <int,int> id[N];
vector <int> edge[N];
vector <pii> lim[N];
vector <int> ht[N];
inline void clear() {
for(int i=1;i<=n;i++) id[i].clear(), lim[i].clear();
for(int i=1;i<=idx;i++) edge[i].clear(), ht[i].clear();
for(int i=1;i<=n;i++) PST::rt0[i]=PST::rt1[i]=0;
PST::tot=0;
}
inline int gl(int x) {return (li[x]==x) ? x : (li[x]=gl(li[x]));}
inline int gr(int x) {return (ri[x]==x) ? x : (ri[x]=gr(ri[x]));}
inline void merge(int x,int y) {ri[x]=y; li[y]=x;}
inline int findl(int l,int r,int v,int ans=0) {
while(l<=r) {
int mid=(l+r)>>1;
if(st[mid].first<=v) r=mid-1;
else ans=st[mid].second, l=mid+1;
} return ans;
}
inline int dfs(int x) {
int rs=0,s=0;
for(auto j:ht[x]) {
rs=max(rs,PST::ask(tr[x].l,tr[x].r,j));
rs=max(rs,PST::ask(tr[x].l,tr[x].r,j+1));
}
rs=max(rs,PST::ask(tr[x].l,tr[x].r,tr[x].h));
for(auto v:edge[x])
s+=dfs(v);
return max(rs,s);
}
int main() {
for(int T=rd();T;T--) {
clear(); n=rd(), m=rd();
for(int i=1;i<n;i++) hi[i]=rd(),st[i]=pii(hi[i],i);
sort(st+1,st+n);
for(int i=1;i<=n;i++) li[i]=ri[i]=i, id[i][i]=ti[i]=++idx, tr[idx]=node(i,i,INF);
for(int i=1,j;i<n;i=j+1) {
j=i; while(j<n-1 && st[j+1].first==st[i].first) ++j;
for(int k=i;k<=j;k++) pl[st[k].second]=gl(st[k].second), pr[st[k].second+1]=gr(st[k].second+1);
for(int k=i;k<=j;k++) merge(st[k].second,st[k].second+1);
for(int k=i;k<=j;k++) {
if(gl(st[k].second)==pl[st[k].second]) {
int l=gl(st[k].second), r=gr(st[k].second);
id[l][r]=++idx; tr[idx]=node(l,r,INF);
}
edge[idx].push_back(ti[pl[st[k].second]]);
tr[ti[pl[st[k].second]]].h=st[k].first-1;
if(gr(st[k].second+1)==pr[st[k].second+1]) {
edge[idx].push_back(ti[st[k].second+1]);
tr[ti[st[k].second+1]].h=st[k].first-1;
}
}
for(int k=i;k<=j;k++) ti[gl(st[k].second)]=id[gl(st[k].second)][gr(st[k].second)];
}
for(int i=1;i<=m;i++) {
int pos=rd(), yc=rd(), ki=rd();
lim[pos].push_back(pii(yc,ki));
} PST::init(lim);
st[tl=1]=pii(INF,1);
for(int i=1;i<=n;i++) {
for(auto &j:lim[i]) {
int l=findl(1,tl,j.first);
j.second=l;
}
while(tl && st[tl].first<hi[i]) --tl;
st[++tl]=pii(hi[i],i+1);
}
st[tl=1]=pii(INF,n);
for(int i=n;i>=1;i--) {
for(auto j:lim[i]) {
int r=findl(1,tl,j.first);
ht[id[j.second][r]].push_back(j.first);
}
while(tl && st[tl].first<hi[i-1]) --tl;
st[++tl]=pii(hi[i-1],i-1);
}
cout<<dfs(idx)<<'\n';
}
}