题目链接

https://www.lydsy.com/JudgeOnline/problem.php?id=4388

题解

模拟Prim算法?
原题所述的过程就是Prim算法求最大生成树的过程。于是我们可以知道起始点并没有影响。
那么就用数据结构模拟Prim算法吧。
首先离散化所有区间,每个区间只需要一个点和外面相连,其余点均按照覆盖该点区间的最大权值与这个点相连。因此简单利用线段树即可求出这一部分的答案。
对于剩下的部分,用维护\(T\)表示目前没有加入的点,先加入左边\(1\)号点,同时用大根堆维护已加入点和未加入点之间的连边(也就是有一部分已加入一部分未加入的区间)
每次从堆中取出一个区间,随便找一个该区间内还在\(T\)集中的点(若不存在就什么都不干),把它从\(T\)集中删掉,顺便把包含它的所有没访问过的区间加入队列
这个可以使用线段树实现,两棵线段树分别维护两边的点,把每个区间拆成\(\log\)段,放到线段树的每个节点上,顺便维护每个区间内依然存在的点的最大值(或最小值,目的就是随便找一个点),每次删掉一个点的时候删掉线段树从根到它的所有区间并扔进堆里,并且把这个点标记为不存在(最大值改成\(0\)).
这一部分使用vector实现可能会MLE,可以使用链表实现。
总时间复杂度\(O(n\log n)\).

代码

#include<bits/stdc++.h>
#define llong long long
#define pii pair<int,int>
#define mkpr make_pair
using namespace std;const int N = 2e5;
const int SIZ = 3.5e6;struct Element
{int lx,ly,rx,ry; llong w;bool operator <(const Element &arg) const {return w>arg.w;}
} qr[N+3];
priority_queue<pii> pq;
bool del[N+3];struct SegmentTree
{struct List{int nxt,val;} li[SIZ+3];struct SgTNode{int fe;int maxi;} sgt[(N<<2)+3];int siz;void build(int u,int le,int ri){sgt[u].maxi = ri;if(le==ri) {return;}int mid = (le+ri)>>1;build(u<<1,le,mid); build(u<<1|1,mid+1,ri);}void insert(int u,int le,int ri,int lb,int rb,int x){if(lb>rb) {return;}if(le>=lb && ri<=rb) {siz++; li[siz].nxt = sgt[u].fe; li[siz].val = x; sgt[u].fe = siz; return;}int mid = (le+ri)>>1;if(lb<=mid) {insert(u<<1,le,mid,lb,rb,x);}if(rb>mid) {insert(u<<1|1,mid+1,ri,lb,rb,x);}}int query(int u,int le,int ri,int lb,int rb){if(lb>rb) {return 0;}if(le>=lb && ri<=rb) {return sgt[u].maxi;}int mid = (le+ri)>>1,ret = 0;if(lb<=mid) {ret = max(ret,query(u<<1,le,mid,lb,rb));}if(rb>mid) {ret = max(ret,query(u<<1|1,mid+1,ri,lb,rb));}return ret;}void delet(int u,int le,int ri,int pos){for(int &i=sgt[u].fe; i; i=li[i].nxt){if(!del[li[i].val]) {del[li[i].val] = true; pq.push(mkpr(qr[li[i].val].w,li[i].val));}}if(le==ri) {sgt[u].maxi = 0; return;}int mid = (le+ri)>>1;if(pos<=mid) {delet(u<<1,le,mid,pos);}else {delet(u<<1|1,mid+1,ri,pos);}sgt[u].maxi = max(sgt[u<<1].maxi,sgt[u<<1|1].maxi);}
} sgt1,sgt2;struct SegmentTree2
{int maxi[(N<<2)+3];void insert(int u,int le,int ri,int lb,int rb,int x){if(lb>rb) return;if(le>=lb && ri<=rb) {maxi[u] = max(maxi[u],x); return;}int mid = (le+ri)>>1;if(lb<=mid) {insert(u<<1,le,mid,lb,rb,x);}if(rb>mid) {insert(u<<1|1,mid+1,ri,lb,rb,x);}}int query(int u,int le,int ri,int pos){if(le==ri) {return maxi[u];}int mid = (le+ri)>>1;if(pos<=mid) {return max(maxi[u],query(u<<1,le,mid,pos));}else {return max(maxi[u],query(u<<1|1,mid+1,ri,pos));}}
} sgt3,sgt4;vector<int> discx,discy;
int n,m,q;
llong ans;int getdiscx(int x) {return lower_bound(discx.begin(),discx.end(),x)-discx.begin();}
int getdiscy(int x) {return lower_bound(discy.begin(),discy.end(),x)-discy.begin();}int main()
{scanf("%d%d%*d%d",&n,&m,&q);for(int i=1; i<=q; i++){scanf("%d%d%d%d%lld",&qr[i].lx,&qr[i].rx,&qr[i].ly,&qr[i].ry,&qr[i].w);discx.push_back(qr[i].lx-1),discx.push_back(qr[i].rx),discy.push_back(qr[i].ly-1),discy.push_back(qr[i].ry);}discx.push_back(0),discy.push_back(0);sort(discx.begin(),discx.end()); discx.erase(unique(discx.begin(),discx.end()),discx.end());sort(discy.begin(),discy.end()); discy.erase(unique(discy.begin(),discy.end()),discy.end());for(int i=1; i<=q; i++){qr[i].lx = getdiscx(qr[i].lx-1)+1,qr[i].rx = getdiscx(qr[i].rx),qr[i].ly = getdiscy(qr[i].ly-1)+1,qr[i].ry = getdiscy(qr[i].ry);}n = discx.size()-1,m = discy.size()-1;sgt1.build(1,1,n); sgt2.build(1,1,m);for(int i=1; i<=q; i++){sgt3.insert(1,1,n,qr[i].lx,qr[i].rx,qr[i].w);sgt4.insert(1,1,m,qr[i].ly,qr[i].ry,qr[i].w);sgt1.insert(1,1,n,qr[i].lx,qr[i].rx,i);sgt2.insert(1,1,m,qr[i].ly,qr[i].ry,i);}for(int i=1; i<=n; i++){ans += 1ll*sgt3.query(1,1,n,i)*(discx[i]-discx[i-1]-1ll);}for(int i=1; i<=m; i++){ans += 1ll*sgt4.query(1,1,m,i)*(discy[i]-discy[i-1]-1ll);}sgt1.delet(1,1,n,1);while(!pq.empty()){int i = pq.top().second; pq.pop();int ux = sgt1.query(1,1,n,qr[i].lx,qr[i].rx);if(ux){ans += qr[i].w;sgt1.delet(1,1,n,ux);pq.push(mkpr(qr[i].w,i));continue;}int uy = sgt2.query(1,1,m,qr[i].ly,qr[i].ry);if(uy){ans += qr[i].w;sgt2.delet(1,1,m,uy);pq.push(mkpr(qr[i].w,i));}}if(sgt1.sgt[1].maxi||sgt2.sgt[1].maxi) {puts("-1"); return 0;}printf("%lld\n",ans);return 0;
}

BZOJ 4388 [JOI2012春季合宿]Invitation (线段树、二叉堆、最小生成树)相关推荐

  1. BZOJ 4221 [JOI2012春季合宿]Kangaroo (DP)

    题目链接 https://www.lydsy.com/JudgeOnline/problem.php?id=4221 题解 orz WYC 爆切神仙DP 首先将所有袋鼠按大小排序.考虑从前往后DP, ...

  2. [JOI2012春季合宿]Rotate (链表)

    题意 题解 又是一道神仙题-- 显然的做法是大力splay,时间复杂度\(O((N+Q)N\log N)\), 可以卡掉. 正解: 使用十字链表维护矩阵,在周围增加第\(0\)行/列和第\((n+1) ...

  3. [JOI2012春季合宿]Constellation (凸包)

    题意 题解 神仙结论题. 结论: 一个点集合法当且仅当其凸包上的两种颜色点分别连续. 证明: 必要性显然. 充分性: 考虑对于一个不同色三角形\(ABC\),不妨设点\(A\)为白点,点\(B,C\) ...

  4. 线段树、二叉堆以及离散化入门

    目录 线段树 例题 题面 练习 1 2 3 4 5 小解区间操作 二叉堆 例题 思路 @ 线段树 例题 题面 时间限制: 1 Sec 内存限制: 128 MB [题意]给出N个数,两种操作:1.C x ...

  5. JOI-2016/17 春季合宿 切题记

    17年的合宿好难啊...感觉是我做过的最难的一套题(没有之一)了...但是可能也是价值最高的? Day1: T1 Cultivation:给你一个H*W的网格,有N<=300棵仙人掌.每一年可以 ...

  6. BZOJ.4553.[HEOI2016TJOI2016]序列(DP 树状数组套线段树/二维线段树(MLE) 动态开点)

    题目链接:BZOJ 洛谷 \(O(n^2)\)DP很好写,对于当前的i从之前满足条件的j中选一个最大值,\(dp[i]=d[j]+1\) for(int j=1; j<i; ++j)if(a[j ...

  7. BZOJ 4043 [HAOI2015]树上操作 dfs序 线段树

    $ \Rightarrow $ 戳我进BZOJ原题 $ \Rightarrow $ 戳我进洛谷原题 [HAOI2015]树上操作 Time Limit: 10 Sec Memory Limit: 25 ...

  8. 【BZOJ 3747】 3747: [POI2015]Kinoman (线段树)

    3747: [POI2015]Kinoman Time Limit: 60 Sec  Memory Limit: 128 MB Submit: 830  Solved: 338 Description ...

  9. bzoj 4653: [Noi2016]区间(尺取+线段树)

    4653: [Noi2016]区间 Time Limit: 60 Sec  Memory Limit: 256 MB Submit: 934  Solved: 500 [Submit][Status] ...

最新文章

  1. 图像超分辨率网络:RCAN
  2. 高频焊台源码,改进版V2
  3. 使用 ASMCMD 工具管理ASM目录及文件
  4. C/C++中调用api设置mysql连接的编码方式
  5. 编程之美3——N!末尾有多少个0
  6. q版地图制作软件_Flash动画的图形元件实例-Q版人物侧面行走
  7. 学习日记-wps表格 工资条的制作
  8. android toast 带图片,Android 带图片的Toast
  9. KS检验-如何理解KS检验中的p-value
  10. 玛丽威廉学院计算机,在美国一流研究型大学任教的部分清华学子
  11. Java程序流程控制(符号函数sgn、闰年判断)
  12. Vim快捷键学习---记性不行了,留这里备查
  13. 第二节 LwIP简介
  14. 英文手写墨水艺术字体
  15. Mac 强制退出程序方法
  16. 177本名著浓缩成了 177句话 、
  17. android vitamio集成教程,集成Vitamio实现万能播放器(示例代码)
  18. 【Transformer开山之作】Attention is all you need原文解读
  19. YDOOK:ANSYS 进行电磁场仿真的第四步:后处理 查看计算结果
  20. 网络安全实训记录(2020.7.15-2020.7.19)

热门文章

  1. 10 年深度学习顶级论文和代码精选,请务必收藏!
  2. tkFileDialog报错,模块未找到出错:没有名字叫做 tkFileDialog 的模块
  3. OpenGL编程指南1:OpenGL简介
  4. 在asp.net 中应用POST传递和接收XML文件以及参数.
  5. 在stringgrid的drawcell事件处理过程中,给单元格赋值时,要用textout输出,不要像一般给cell[i,j]赋值那样。
  6. 计算机网络核心知识(中)
  7. Java判断首个或最后字符或者字符串是否为指定的字符/字符串
  8. 使用HttpSessionBindingListener方法
  9. HashMap(Java)
  10. 操作系统(二十)进程互斥的硬件实现方法