【题解】 [JOISC2020] 星座 3

solution:

考虑怎样的一对星星会形成星座。

l [ i ] l[i] l[i] r [ i ] r[i] r[i] 分别表示从第 i i i 个星星出发,能扩展到的最左和最右节点。

考虑反悔贪心,尽量使得答案更大。换句话说,当前点覆盖的区间一定比之前 [ l [ i ] , r [ i ] ] [l[i],r[i]] [l[i],r[i]] 内所有点管辖的区间的并集还大,所以如果 w ≥ c w\geq c wc 那么答案直接加上 c c c ;否则强行选择当前星星,自然而然地对 [ l [ i ] , r [ i ] ] [l[i],r[i]] [l[i],r[i]] 加上 C − W C-W CW 的价值表示翻转的代价。(定义反转操作为弃掉 s 而把选择 s 所弃掉的全部选回来)。

然后并查集细节比较多,但是 高度有单调性,应该是在 a [ i ] a[i] a[i] 处取出来,合并前把 y y y 处星星取出来,然后单点查询 + 区间修改。(因为这里有传递性,所以选这个星星就只有不选它和将 [ l [ i ] , r [ i ] ] [l[i],r[i]] [l[i],r[i]] 全部弃掉两种情况)。

不知道理解得对不对 qwq …

#include<bits/stdc++.h> #define PII pair<int,int> #define ll long long using namespace std; const int mx=2e5+5; int n,m,a[mx],l[mx],r[mx]; ll res,bit[mx]; vector<PII> s[mx]; vector<int> h[mx]; void upd(int x,ll k) { for(int i=x;i<=n;i+=i&-i) bit[i]+=k; } ll qry(int x) { ll tot(0); for(int i=x;i;i-=i&-i) tot+=bit[i]; return tot; } int find(int x,int *fa) { return fa[x]==x?x:fa[x]=find(fa[x],fa); } int main() { // freopen("data.in","r",stdin); scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&a[i]),h[a[i]].push_back(i); for(int i=0;i<=n+1;i++) l[i]=i,r[i]=i; scanf("%d",&m); for(int i=1;i<=m;i++) { int x,y,c; scanf("%d%d%d",&x,&y,&c); s[y].push_back(make_pair(x,c)); } for(int i=1;i<=n;i++) { for(auto x:s[i]) { ll w=qry(x.first),c=x.second; if(w>=c) res+=c; else res+=w,upd(find(x.first,l)+1,c-w),upd(find(x.first,r),w-c); } for(auto x:h[i]) { l[x]=x-1,r[x]=x+1; } } printf("%lld",res); }

__EOF__

本文作者仰望星空的蚂蚁
本文链接https://www.cnblogs.com/cqbzly/p/17530273.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   仰望星空的蚂蚁  阅读(14)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· DeepSeek 开源周回顾「GitHub 热点速览」
点击右上角即可分享
微信分享提示