loj#2740. 「JOISC 2016 Day 4」最差记者 2
为啥网上这题很少有题解啊。
首先,改 A 和改 C 是一样的,我们考虑只改 C。让 D 去匹配 B。
有一个比较好想的做法,先考虑能够同国匹配的就先匹配掉(这个可以用 multiset),剩余的,考虑按值域来(实际上离散化后就是跟按序列一样),对于 ,那么所对应 的值域在 。
那么,分成 2 个部分,将 D 部的 连向 B 部的 这些点。那么,我们只需要看看有没有完美匹配即可。
假如同国匹配的全都匹配掉之后再去看看有没有完美匹配,则可能不行。
我们要让最后一定有完美匹配,所以对于同国能匹配的,还要判断删去 D 部这个点,还能不能形成完美匹配。
但这样复杂度是 级别的。
考虑只需要判断有没有,想到 hall 定理。
即 。
按照套路维护前缀 。对于 ,那么会对 有贡献(我们是让 D 部匹配 B 部嘛)贡献范围是 (前缀集合大小贡献),对于 ,对 有贡献,贡献范围是 ,即对于 ,才可能匹配它。
这个样子相当于 ,用线段树维护前缀最小值即可。(注意是前缀,因为要表示子集!!!为什么可以看另一道相似的题目的题解)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 | <code-pre class = "code-pre" id= "pre-NkiaBi" ><code-line class = "line-numbers-rows" ></code-line>#include <cstdio> <code-line class = "line-numbers-rows" ></code-line>#include <algorithm> <code-line class = "line-numbers-rows" ></code-line>#include <iostream> <code-line class = "line-numbers-rows" ></code-line>#include <cstring> <code-line class = "line-numbers-rows" ></code-line>#include <vector> <code-line class = "line-numbers-rows" ></code-line>#include <cmath> <code-line class = "line-numbers-rows" ></code-line>#include <queue> <code-line class = "line-numbers-rows" ></code-line>#include <map> <code-line class = "line-numbers-rows" ></code-line>#include <set> <code-line class = "line-numbers-rows" ></code-line>#define ll long long <code-line class = "line-numbers-rows" ></code-line> <code-line class = "line-numbers-rows" ></code-line> using namespace std; <code-line class = "line-numbers-rows" ></code-line> int rd() { <code-line class = "line-numbers-rows" ></code-line> int f=1,sum=0; char ch= getchar (); <code-line class = "line-numbers-rows" ></code-line> while (! isdigit (ch)) { if (ch== '-' ) f=-1;ch= getchar ();} <code-line class = "line-numbers-rows" ></code-line> while ( isdigit (ch)) {sum=(sum<<3)+(sum<<1)+ch- '0' ;ch= getchar ();} <code-line class = "line-numbers-rows" ></code-line> return sum*f; <code-line class = "line-numbers-rows" ></code-line>} <code-line class = "line-numbers-rows" ></code-line>ll lrd() { <code-line class = "line-numbers-rows" ></code-line> ll f=1,sum=0; char ch= getchar (); <code-line class = "line-numbers-rows" ></code-line> while (! isdigit (ch)) { if (ch== '-' ) f=-1;ch= getchar ();} <code-line class = "line-numbers-rows" ></code-line> while ( isdigit (ch)) {sum=(sum<<3)+(sum<<1)+ch- '0' ;ch= getchar ();} <code-line class = "line-numbers-rows" ></code-line> return sum*f; <code-line class = "line-numbers-rows" ></code-line>} <code-line class = "line-numbers-rows" ></code-line> /* <code-line class="line-numbers-rows"></code-line>考虑改A和改C没区别 <code-line class="line-numbers-rows"></code-line>让结束的这一部去匹配之前的那一部 <code-line class="line-numbers-rows"></code-line>且维护线段树前缀和,这时对于点数就不一定是 l 了 <code-line class="line-numbers-rows"></code-line>可以考虑动态加 <code-line class="line-numbers-rows"></code-line>*/ <code-line class = "line-numbers-rows" ></code-line>#define ls (cur<<1) <code-line class = "line-numbers-rows" ></code-line>#define rs (ls|1) <code-line class = "line-numbers-rows" ></code-line>#define int ll <code-line class = "line-numbers-rows" ></code-line> const int N=( int )(5e5+5); <code-line class = "line-numbers-rows" ></code-line>multiset< int >s[N]; <code-line class = "line-numbers-rows" ></code-line>multiset< int >::iterator it; <code-line class = "line-numbers-rows" ></code-line> int mi[N<<2],tag[N<<2],A[N],B[N],C[N],D[N],lsh[N<<1],tot,n; <code-line class = "line-numbers-rows" ></code-line> <code-line class = "line-numbers-rows" ></code-line> void push_up( int cur) { <code-line class = "line-numbers-rows" ></code-line> mi[cur]=min(mi[ls],mi[rs]); <code-line class = "line-numbers-rows" ></code-line>} <code-line class = "line-numbers-rows" ></code-line> <code-line class = "line-numbers-rows" ></code-line> void push_down( int cur) { <code-line class = "line-numbers-rows" ></code-line> if (!tag[cur]) return ; <code-line class = "line-numbers-rows" ></code-line> tag[ls]+=tag[cur]; tag[rs]+=tag[cur]; <code-line class = "line-numbers-rows" ></code-line> mi[ls]+=tag[cur]; mi[rs]+=tag[cur]; <code-line class = "line-numbers-rows" ></code-line> tag[cur]=0; <code-line class = "line-numbers-rows" ></code-line>} <code-line class = "line-numbers-rows" ></code-line> <code-line class = "line-numbers-rows" ></code-line> void update( int cur, int l, int r, int cl, int cr, int v) { <code-line class = "line-numbers-rows" ></code-line> if (cl<=l&&r<=cr) return mi[cur]+=v,tag[cur]+=v, void (); <code-line class = "line-numbers-rows" ></code-line> push_down(cur); <code-line class = "line-numbers-rows" ></code-line> int mid=(l+r)>>1; <code-line class = "line-numbers-rows" ></code-line> if (cl<=mid) update(ls,l,mid,cl,cr,v); <code-line class = "line-numbers-rows" ></code-line> if (cr>mid) update(rs,mid+1,r,cl,cr,v); <code-line class = "line-numbers-rows" ></code-line> push_up(cur); <code-line class = "line-numbers-rows" ></code-line>} <code-line class = "line-numbers-rows" ></code-line> <code-line class = "line-numbers-rows" ></code-line> signed main() { <code-line class = "line-numbers-rows" ></code-line> n=rd(); <code-line class = "line-numbers-rows" ></code-line> for ( int i=1;i<=n;i++) A[i]=rd(),B[i]=rd(),lsh[++tot]=B[i]; <code-line class = "line-numbers-rows" ></code-line> for ( int i=1;i<=n;i++) C[i]=rd(),D[i]=rd(),lsh[++tot]=D[i]; <code-line class = "line-numbers-rows" ></code-line> sort(lsh+1,lsh+1+tot); tot=unique(lsh+1,lsh+1+tot)-lsh-1; <code-line class = "line-numbers-rows" ></code-line> for ( int i=1;i<=n;i++) { <code-line class = "line-numbers-rows" ></code-line> B[i]=lower_bound(lsh+1,lsh+1+tot,B[i])-lsh; D[i]=lower_bound(lsh+1,lsh+1+tot,D[i])-lsh; <code-line class = "line-numbers-rows" ></code-line> s[A[i]].insert(B[i]); <code-line class = "line-numbers-rows" ></code-line> update(1,1,tot,B[i],tot,1); //匹配的点数,只能是之后的 <code-line class = "line-numbers-rows" ></code-line> update(1,1,tot,D[i],tot,-1); //前缀的集合+1 <code-line class = "line-numbers-rows" ></code-line> } <code-line class = "line-numbers-rows" ></code-line> int ans=0; <code-line class = "line-numbers-rows" ></code-line> for ( int i=n;i>=1;i--) { <code-line class = "line-numbers-rows" ></code-line> it=s[C[i]].upper_bound(D[i]); <code-line class = "line-numbers-rows" ></code-line> if (it==s[C[i]].begin()) ++ans; <code-line class = "line-numbers-rows" ></code-line> else { <code-line class = "line-numbers-rows" ></code-line> --it; int qwq=*it; <code-line class = "line-numbers-rows" ></code-line> s[C[i]].erase(it); <code-line class = "line-numbers-rows" ></code-line> update(1,1,tot,qwq,tot,-1); update(1,1,tot,D[i],tot,1); <code-line class = "line-numbers-rows" ></code-line> if (mi[1]<0) { //剩下的没有完美匹配 <code-line class = "line-numbers-rows" ></code-line> s[C[i]].insert(qwq); ++ans; <code-line class = "line-numbers-rows" ></code-line> update(1,1,tot,qwq,tot,1); update(1,1,tot,D[i],tot,-1); <code-line class = "line-numbers-rows" ></code-line> } <code-line class = "line-numbers-rows" ></code-line> } <code-line class = "line-numbers-rows" ></code-line> } <code-line class = "line-numbers-rows" ></code-line> printf ( "%lld" ,ans); return 0; <code-line class = "line-numbers-rows" ></code-line>} </code-pre> |
__EOF__

本文作者:F x o r G
本文链接:https://www.cnblogs.com/xugangfan/p/15211229.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是博主的最大动力!
本文链接:https://www.cnblogs.com/xugangfan/p/15211229.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是博主的最大动力!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】