Advertisement Matching

题解

首先,题目的 a , b a,b a,b匹配显然是一个很常见的贪心。
有结论,设 a a a的集合为 A A A,如果 ∀ S ⊆ A , ∑ a i ∈ S a i ⩽ ∑ i = 1 m min ⁡ ( b i , ∣ S ∣ ) \forall S\subseteq A,\sum_{a_{i}\in S}a_{i}\leqslant \sum_{i=1}^{m}\min(b_{i},|S|) ∀S⊆A,∑ai​∈S​ai​⩽∑i=1m​min(bi​,∣S∣),那么一定存在一种匹配的方法,使得该题的要求成立。
这也就是Gale–Ryser theorem,这里有一种通过网络流的证明,我个人是通过类贪心的思想理解的。

证明:
该结论的必要性是显然的,我们只需要证明其的充分性,也就是满足上面结论时一定有解。
具体来说,由于对于相同的 ∣ S ∣ |S| ∣S∣,后面的 ∑ i = 1 m min ⁡ ( b i , ∣ S ∣ ) \sum_{i=1}^{m}\min(b_{i},|S|) ∑i=1m​min(bi​,∣S∣)的值肯定是一定的。
而前面 ∑ a i ∈ S a i \sum_{a_{i}\in S}a_{i} ∑ai​∈S​ai​的最大时肯定是选择 A A A集合中最大的几个数,我们只需要让这些数的和小于我们后面的值就行了。
如果该集合中的最小值,该式不成立,那显然是不行的,我们不妨假定我们去掉最小值时是成立的,现在要将这个最小值加进去。
我们可以将原来的图形根据 min ⁡ ( b i , ∣ S ∣ ) \min(b_{i},|S|) min(bi​,∣S∣)想象成柱状图,我们现在新加入一个数,肯定有几个柱子会被拔高,而我们的限制是一个柱子最多只能选择一个位置染色。
如果最开始的柱状图就空出一行及以上,如果新加入的 a i ⩽ m a_{i}\leqslant m ai​⩽m,显然是有位置的,如果 a i > m a_{i}> m ai​>m,之前的肯定也比 m m m大,那之前就判无解了。
否则,如果没有空出一行以上,而我们让延伸的延伸,此时的空位个数肯定不会小于 a i a_{i} ai​,如果,能填满就填,不能填满,肯定是有新延伸的空位原来也是空位。
注意,现在还在延伸的位置,之前肯定也是在延伸的,故之前必然是有一个 a i a_{i} ai​覆盖了没有延伸的位置,却没有覆盖新延伸的位置,我们可以让它覆盖的位置改变一下,将覆盖没有延伸位置的地方改成覆盖延伸了的为的地方。
由于之前的 a a a都不小于 a i a_{i} ai​,所以我们一定可以通过这种方法调整到让 a i a_{i} ai​有位置可填。
这样就可以证明该式的充分性了。

证明了上面的结论,我们自然也就想到了如何维护原题是否可行的方法。
我们可以先将 a a a值排序,保证我们选择的 S S S大小固定时,我们所选择的 a a a的和是最大的。
此时,如果 ∀ k ∈ [ 1 , n ] , ∑ i = 1 m min ⁡ ( b i , k ) − ∑ i = 1 k a i ⩾ 0 \forall k\in[1,n],\sum_{i=1}^{m}\min(b_{i},k)-\sum_{i=1}^{k}a_{i}\geqslant 0 ∀k∈[1,n],∑i=1m​min(bi​,k)−∑i=1k​ai​⩾0成立,那么我们是一定有解的,否则一定无解。
我们显然可以通过线段树维护不同的 k k k的值,如果 min ⁡ k = 1 n ( ∑ i = 1 m min ⁡ ( b i , k ) − ∑ i = 1 k a i ) ⩾ 0 \min_{k=1}^{n}\left(\sum_{i=1}^{m}\min(b_{i},k)-\sum_{i=1}^{k}a_{i}\right)\geqslant 0 mink=1n​(∑i=1m​min(bi​,k)−∑i=1k​ai​)⩾0,就有解。
如果 b i + 1 b_{i}+1 bi​+1,显然会让 k ⩾ b i + 1 k\geqslant b_{i}+1 k⩾bi​+1的部分,上式的值 + 1 +1 +1。
而 b i − 1 b_{i}-1 bi​−1则会让 k ⩾ b i k\geqslant b_{i} k⩾bi​的部分,上式 − 1 -1 −1。
由于我们 b b b的加值是取的 min ⁡ ( b i , k ) \min(b_{i},k) min(bi​,k),这是显然的。
而 a i a_{i} ai​的改变则涉及到了该元素的 r k rk rk,记 r k x rk_{x} rkx​表示大于等于 x x x的数的个数。
如果 a i + 1 a_{i}+1 ai​+1,那么 k ⩾ r k a i + 1 + 1 k\geqslant rk_{a_{i}+1}+1 k⩾rkai​+1​+1的部分,上式值会 + 1 +1 +1,再让 r k a i + 1 + + rk_{a_{i}+1}++ rkai​+1​++。
而 a i − 1 a_{i}-1 ai​−1,会让 k ⩾ r k a i k\geqslant rk_{a_{i}} k⩾rkai​​的部分值 − 1 -1 −1,再让 r k a i − − rk_{a_{i}}-- rkai​​−−。
以上的四种操作都是线段树上区间的修改,我们只用看修改完的的最小值就行了。

时间复杂度 O ( n + m + q log ⁡ n ) O\left(n+m+q\log\,n\right) O(n+m+qlogn)。

源码

#include<bits/stdc++.h>
using namespace std;
#define MAXN 250005
#define lowbit(x) (x&-x)
#define reg register
#define pb push_back
#define mkpr make_pair
#define fir first
#define sec second
#define lson (rt<<1)
#define rson (rt<<1|1)
typedef long long LL;
//#define int LL
typedef unsigned long long uLL;
const LL INF=0x3f3f3f3f3f3f3f3f;
const int mo=998244353;
const int inv2=499122177;
const int jzm=2333;
const int n1=50;
const int lim=250000;
const int zero=10000;
const int orG=3,invG=332748118;
const double Pi=acos(-1.0);
const double eps=1e-5;
typedef pair<LL,int> pii;
template<typename _T>
_T Fabs(_T x){return x<0?-x:x;}
template<typename _T>
void read(_T &x){_T f=1;x=0;char s=getchar();while(s>'9'||s<'0'){if(s=='-')f=-1;s=getchar();}while('0'<=s&&s<='9'){x=(x<<3)+(x<<1)+(s^48);s=getchar();}x*=f;
}
template<typename _T>
void print(_T x){putchar('\n');while(x>9){putchar((x%10)|'0');x/=10;}putchar(x|'0');}
LL gcd(LL a,LL b){return !b?a:gcd(b,a%b);}
int add(int x,int y,int p){return x+y<p?x+y:x+y-p;}
void Add(int &x,int y,int p){x=add(x,y,p);}
int qkpow(int a,int s,int p){int t=1;while(s){if(s&1LL)t=1ll*a*t%p;a=1ll*a*a%p;s>>=1LL;}return t;}
int n,m,q,a[MAXN],b[MAXN],c[MAXN],d[MAXN],rk[MAXN];
LL dif[MAXN],val[MAXN];
class SegmentTree{private:LL minn[MAXN<<2],lzy[MAXN<<2];//void pushup(int rt){minn[rt]=min(minn[lson],minn[rson]);}#define pushup(rt) minn[rt]=min(minn[lson],minn[rson])void pushdown(int rt){if(lzy[rt]){minn[lson]+=lzy[rt];lzy[lson]+=lzy[rt];minn[rson]+=lzy[rt];lzy[rson]+=lzy[rt];lzy[rt]=0;}}public:void build(int rt,int l,int r){if(l==r){minn[rt]=val[l];return ;}int mid=l+r>>1;build(lson,l,mid);build(rson,mid+1,r);pushup(rt);}void modify(int rt,int l,int r,int al,int ar,LL aw){if(l>r||l>ar||r<al||al>ar)return ;if(al<=l&&r<=ar){minn[rt]+=aw;lzy[rt]+=aw;return ;}int mid=l+r>>1;pushdown(rt);if(al<=mid)modify(lson,l,mid,al,ar,aw);if(ar>mid)modify(rson,mid+1,r,al,ar,aw);pushup(rt);}void search(int rt,int l,int r){if(l==r){printf("%d ",minn[rt]);return ;}int mid=l+r>>1;pushdown(rt);search(lson,l,mid);search(rson,mid+1,r);}LL ask(){return minn[1];} bool query(){return minn[1]>=0;}
}T;
signed main(){read(n);read(m);LL summ=0;for(int i=1;i<=n;i++)read(a[i]),c[i]=-a[i],rk[a[i]]++;for(int i=1;i<=m;i++)read(b[i]),d[i]=b[i];sort(c+1,c+n+1);sort(d+1,d+m+1);for(int i=lim;i>0;i--)rk[i]+=rk[i+1];for(int i=1,j=1;i<=n;i++){while(j<=m&&d[j]<=i)summ+=1ll*d[j],j++;summ+=1ll*c[i];val[i]=summ+1ll*i*(m-j+1);}T.build(1,1,n);read(q);for(int i=1;i<=q;i++){int opt,x;read(opt);read(x);if(opt==1)a[x]++,rk[a[x]]++,T.modify(1,1,n,rk[a[x]],n,-1);if(opt==2)T.modify(1,1,n,rk[a[x]],n,1),rk[a[x]]--,a[x]--;if(opt==3)b[x]++,T.modify(1,1,n,b[x],n,1);if(opt==4)T.modify(1,1,n,b[x],n,-1),b[x]--;printf("%d\n",T.query());}return 0;
}

谢谢!!!

[XXI Open Cup.Grand Prix of Korea]Advertisement Matching相关推荐

  1. XXI Open Cup. Grand Prix of Korea I. Query On A Tree 17 树剖 + 二分 + 树带权重心

    传送门 文章目录 题意: 思路: 题意: 给你一棵树,每棵树初始权值都为000,现在给你两个操作: (1)(1)(1)将uuu的子树权值全部加111. (2)(2)(2)将(u,v)(u,v)(u,v ...

  2. 2020-2021 Winter Petrozavodsk Camp, Belarusian SU Contest (XXI Open Cup, Grand Prix of Belarus)

    题目链接 C. Brave Seekers of Unicorns 给出一个好数组的定义: 1.1.1. 长度不为空 2.2.2. a[i]⨁a[i−1]⨁a[i−2]≠0a[i] \bigoplus ...

  3. [XXII Open Cup, Grand Prix of Korea M]Yet Another Range Query Problem

    Yet Another Range Query Problem 题解 首先,看到这道题,我们应该是比较容易联想到扫描线加线段树的. 我们考虑维护每个点作为左端点到当前扫到的这个点作为右端点之间区间的信 ...

  4. G-Lexicographically Minimum Walk[CF-Gym-102391][2019-2020 XX Open Cup, Grand Prix of Korea]

    原题传送门 题面 Lexicographically Minimum Walk time limit per test2 secondsmemory limit per test1024 megaby ...

  5. 2020-2021 ACM-ICPC, Asia Nanjing Regional Contest (XXI Open Cup, Grand Prix of Nanjing)

    M. Monster Hunter 树形背包dp dp[i][j][k] 表示结点i的子树中有j个节点存活且当前节点i的状态为(0/1) 转移方程: dp[x][i+j][0]=min(dp[x][i ...

  6. [XXI Open Cup,Grand Prix of Tokyo]Ascending Matrix

    Ascending Matrix 题解 首先,这道题是要求所有的数列是从上往下,从左往右,都是递增的. 首先从左往右递增,我们可以去考虑它的差分序列,每个点的值就是它前面差分序列的点数嘛. 从上往下递 ...

  7. XVIII Open Cup named after E.V. Pankratiev. Grand Prix of Korea

    A. Donut 扫描线+线段树. #include<cstdio> #include<algorithm> using namespace std; typedef long ...

  8. 2015-2016 XVI Open Cup, Grand Prix of Bashkortostan, SKB Kontur Cup Stage 2

    地址 Rank Solved A B C D E F G H I J K L M 72/213 8/13 O . O O . O . O O O . O Ø O: 当场通过 Ø: 赛后通过 .: 尚未 ...

  9. XVIII Open Cup named after E.V. Pankratiev. Grand Prix of SPb

    A. Base $i - 1$ Notation 两个性质: $2=1100$ $122=0$ 利用这两条性质实现高精度加法即可. 时间复杂度$O(n)$. #include<stdio.h&g ...

最新文章

  1. 2021-02-23 如何用简单易懂的例子解释条件随机场(CRF)模型?它和HMM有什么区别?从HMM、MEMM、CRF某牛自己总结的
  2. 华为USG地址池方式的NAPT和NAT Server配置案例
  3. 抓包概念大比较:数据报、数据包、分组
  4. Chrome 技术篇-console控制台检测xpath、css唯一性
  5. while(getchar()=='\n')continue;为什么作用是清空行
  6. 创建css的时候选择器有哪几类,CSS3-CSS的选择器共有几类?
  7. php strpos与strrpos,PHP开发之 strpos stripos strrpos strripos的区别
  8. 人际关系的55个绝招
  9. jquery插件制作 -- 3.表单验证
  10. 学习笔记(十五)——镜像的知识点与注意事项
  11. 腾讯云服务器CentOS 7安装Tomcat并部署JSP站点统计进入站点人数
  12. MongoDB更新文档(非常详细,不要错过~)
  13. mongodb linux用户验证登陆,转载:linux下mongodb的用户查询_【Linux】MongoDB创建数据库(开启用户认证)...
  14. 设置公众号字体大小不跟随微信浏览器字体大小变化
  15. 计算机高考计划,职中高三计算机高考复习计划
  16. Android各种屏幕尺寸
  17. 嵌入式工程师常见C语言手写面试题,摘录于RTT内核源码
  18. WIN7使用手机蓝牙共享网络,及利用蓝牙及WLAN实现双网卡同时上内外网
  19. 数据库实现递归查询,获取节点的所有子孙节点
  20. PHPstorm 函数或者方法的注释的时间和用户名,PHPstorm里函数方法的注释是没有动态时间设置的,但是看了PHP file里面有时间日期的注释,而PHP Function Doc Commen

热门文章

  1. DevStream 成为 CNCF Sandbox 项目啦!- 锣鼓喧天、鞭炮齐鸣、红旗招展、忘词了。
  2. [FROM WOJ]#1232 互不侵犯
  3. 知道106短信平台发短信为什么必须带上签名吗?
  4. linux 平铺式桌面,Linux下5 个很酷的平铺窗口管理器
  5. C++/Qt 使用OpenCV打开摄像头,旋转视频,计算fps
  6. systemd 的网络管理
  7. 微服务与CQRSamp;EventSourcing
  8. 超六成受访者 支持禁用微信布置作业
  9. 牛逼!JetBrains 又出了一款编程神器!协同编程!
  10. 95分 AirPods (单只)开箱:这个二手平台,震惊到我了