[loj3277]星座3
如果不合法,利用贪心发现当且仅当某两个星星所构成的矩形中没有白点
反过来,考虑留下若干个星星,那么即要求留下的星星两两之间满足:$\max_{x_{1}\le i\le x_{2}}a_{i}\ge \min(y_{1},y_{2})$
考虑笛卡尔树,那么在笛卡尔树上这等价于使得两点lca的高度大于等于两点最低高度,由于$a_{fa}\ge a_{k}$($fa$为$k$在lca上的父亲),因此这又等价于要求以$k$为根的子树中最多只能保留1个数比$a_{k}$大
令$f[i][j]$表示以$i$为根的子树中最高不超过为$j$且合法的最大保留的价值,其合法状态数量为不超过子树中点数量,因此启发式合并即可维护,时间复杂度为$o(n\log^{2}n)$
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 200005 4 #define ll long long 5 set<pair<ll,ll> >::iterator it; 6 set<pair<ll,ll> >s[N]; 7 int n,m,x,y,z,a[N],st[N],ls[N],rs[N],f[N]; 8 long long ans,mx[N],tag[N]; 9 int find(int k){ 10 if (k==f[k])return k; 11 return f[k]=find(f[k]); 12 } 13 void merge(int x,int y,int k){ 14 x=find(x),y=find(y); 15 while ((s[y].size())&&((*s[y].begin()).first<=k)){ 16 mx[y]=max(mx[y],(*s[y].begin()).second+tag[y]); 17 s[y].erase(s[y].begin()); 18 } 19 if (s[x].size()<s[y].size()){ 20 f[x]=y; 21 swap(x,y); 22 } 23 tag[x]+=mx[y]; 24 tag[y]+=mx[x]; 25 mx[x]+=mx[y]; 26 for(it=s[y].begin();it!=s[y].end();it++) 27 s[x].insert(make_pair((*it).first,(*it).second+tag[y]-tag[x])); 28 } 29 void dfs(int k){ 30 if (!k)return; 31 dfs(ls[k]); 32 dfs(rs[k]); 33 merge(k,ls[k],a[k]); 34 merge(k,rs[k],a[k]); 35 } 36 int main(){ 37 scanf("%d",&n); 38 for(int i=1;i<=n;i++)scanf("%d",&a[i]); 39 for(int i=1;i<=n;i++)f[i]=i; 40 for(int i=1;i<=n;i++){ 41 while ((st[0])&&(a[st[st[0]]]<a[i]))ls[i]=st[st[0]--]; 42 if (st[0])rs[st[st[0]]]=i; 43 st[++st[0]]=i; 44 } 45 scanf("%d",&m); 46 for(int i=1;i<=m;i++){ 47 scanf("%d%d%d",&x,&y,&z); 48 s[x].insert(make_pair(y,z)); 49 ans+=z; 50 } 51 dfs(st[1]); 52 x=find(st[1]); 53 for(it=s[x].begin();it!=s[x].end();it++)mx[x]=max(mx[x],tag[x]+(*it).second); 54 printf("%lld",ans-mx[x]); 55 }