题意

传送门
大概是让构造使得不存在矩形不包含白楼房,却包含至少两颗星星,并使得删除星星的\(c\)和最小。

思路

同学说这种矩形问题,考虑笛卡尔树。
两个星星能共存取决于中间\(a\)的最大值。
建出大跟堆笛卡尔树。方便处理,把问题变为选出星星的和最大。
假如以笛卡尔树中一个节点作为最大值\(v\),因此相当于考虑两边的合并。
Q:1.合并什么?(存的状态)
2.怎么合并(这个肯定能想到用线段树合并
合并两边分别的多个点,实际上只需要知道两边星星的最高点。而且最多只有一边高于\(v\)
因此状态是\(f[u][j]\)表示\(u\)子树内星星最高点为\(j\)的权值和最大。第一个问题解决。
第二个问题涉及具体操作了:分别查询左右两边最高点在\([1,v]\)的最大值(区间最大值查询),加到对方的\([v+1,n]\)处(区间加add_tag)
解决了一边高一边低的情况。再来合并两边都为\([1,v]\)
发现不会,其实这里取了。发现只需要(\([1,v]\))前缀最大值,而且是大根笛卡尔树,祖先上的\(v\)一定比现在的\(v\)大,即直接两边前缀最大值的和(一开始其实求过了,记下就好)把答案存在\(v\)处就行了。
最后不要忘了merge两棵线段树(合并权值max)。
语言文字不直观,直接看code的merge部分吧。还有,我是贺的
复杂度:\(O(nlogn)\)

code

点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define fi first
#define sc second
typedef long long ll;
typedef pair<int,int> PII;

const int N=1e6+5;
const int M=2e7+5;
int a[N],n,m;
vector<pair<int,int> > star[N];

int son[N][2],st[N],tp,root;
void Build() {
	for(int i=1;i<=n;i++) {
		while(tp&&a[st[tp]]<a[i]) {tp--;}
		son[i][0]=son[st[tp]][1];
		son[st[tp]][1]=i;
		st[++tp]=i;
	}
	root=son[0][1];
}

ll mx[M],tag[M];
int ls[M],rs[M],nd,rt[N];

void Chg(int x,ll w) {if(x)mx[x]+=w,tag[x]+=w;}
void P_up(int x) {mx[x]=max(mx[ls[x]],mx[rs[x]]);}
void P_dw(int x) {
	if(!tag[x])return;
	Chg(ls[x],tag[x]);
	Chg(rs[x],tag[x]);
	tag[x]=0;
}

void Insert(int &x,int l,int r,int p,ll val) {
	if(!x)x=++nd; mx[x]=max(mx[x],val);
	if(l==r) {return;}
	P_dw(x);
	int mid=(l+r)>>1;
	(p<=mid)?Insert(ls[x],l,mid,p,val):Insert(rs[x],mid+1,r,p,val);
}

void Add(int o,int l,int r,int x,int y,ll val) {
	if(!o)return;
	if(x<=l&&r<=y) {Chg(o,val);return;}
	int mid=(l+r)>>1;
	P_dw(o);
	if(x<=mid)Add(ls[o],l,mid,x,y,val);
	if(y>mid)Add(rs[o],mid+1,r,x,y,val);
	P_up(o);
}
int X,Y;
ll Mx(int o,int l,int r,int x,int y) {
	if(!o)return 0;
	if(x<=l&&r<=y) {return mx[o];}
	int mid=(l+r)>>1;ll mx=0;
	P_dw(o);
	if(x<=mid) {mx=Mx(ls[o],l,mid,x,y);}
	if(y>mid)mx=max(mx,Mx(rs[o],mid+1,r,x,y));
	return mx;
}

int tot=0;
int merge(int x,int y) {
	if(!x||!y)return x+y;
	mx[x]=max(mx[x],mx[y]);
	P_dw(x);P_dw(y);
	ls[x]=merge(ls[x],ls[y]),rs[x]=merge(rs[x],rs[y]);
	return x;
}

void Merge(int x,int y,int v) {
	ll wL=Mx(rt[x],1,n,1,v),wR=Mx(rt[y],1,n,1,v);
	if(v<n)Add(rt[x],1,n,v+1,n,wR),Add(rt[y],1,n,v+1,n,wL);
	rt[x]=merge(rt[x],rt[y]);
	Insert(rt[x],1,n,v,wL+wR);
}
void dfs(int u) {
	for(int i=0;i<star[u].size();i++) {
		Insert(rt[u],1,n,star[u][i].fi,star[u][i].sc);
	}
	if(son[u][0]) {dfs(son[u][0]);Merge(u,son[u][0],a[u]);}
	if(son[u][1]) {dfs(son[u][1]);Merge(u,son[u][1],a[u]);}
}

int main() {
	scanf("%d",&n);
	for(int i=1;i<=n;i++){scanf("%d",&a[i]);assert(a[i]<=n);}
	Build();
	scanf("%d",&m);
	ll sumc=0;
	for(int i=1;i<=m;i++) {
		int x,y,c;scanf("%d%d%d",&x,&y,&c);
		sumc+=c;
		star[x].push_back(make_pair(y,c));
	}
	dfs(root);
	
	printf("%lld",sumc-mx[rt[root]]);
	return 0;
}