当前位置: 首页 > article >正文

CF EDU ROUND 172

C

枚举断点贪心

一个01串,1表示归b,0表示归b。可以把这个串分成m个区间,从左往右第i个区间里的每个元素权值都是 i − 1 i-1 i1,问至少划分成几个区间, b b b的分数- a a a的分数不少于
k k k

这种直接想怎么划分,化成几段不好想,可以从每次操作的变化入手。具体来说,可以考虑再一个位置划分后, b − a b-a ba会怎么变化,左边的显然不变右侧的所有元素,所在区间编号都+1了,其中1对答案的贡献本来就是 i d id id,现在变成 i d + 1 id+1 id+1了,贡献增加右侧1的个数,0对答案的贡献原本是 − i d -id id,现在是 − ( i d + 1 ) -(id+1) (id+1),贡献减少右侧0的个数。

因此在一个地方划分,对答案的影响就是右侧1的个数-0的个数。我们可以对这个影响降序排序,然后找前缀,直到贡献加起来大于k。如果全加起来都不到k,那么无解

void solve(){
	cin>>n>>k;
	vi b;
	string s;
	cin>>s;
	s=' '+s;
	
	int sum=0;
	rep1(i,n,2){
		if(s[i]=='1')sum++;
		else sum--;
		b.pb(sum);
	}
	sort(b.begin(),b.end(),[&](int x,int y){
		return x>y;
	});
	int ans=0;
	for(int x:b){
		if(k>x){
			k-=x;
			ans++;
		}
		else{
			ans++;
			k=0;
			break;
		}
	}
	if(k)cout<<-1<<'\n';
	else cout<<ans+1<<'\n';
}

D

给一堆区间,对于一个区间,所有包含这个区间的其他区间的交集大小,减去这个区间的大小,就是这个区间的推荐集合的大小,我们要求这个值。

转化一下,包含一个区间的所有区间,实际上就是 l 1 < = l , r 1 > = r l_1<=l,r_1>=r l1<=l,r1>=r,这是个二位偏序,我们可以排序+线段树,遍历每个区间和包含它的所有区间。然后我们要求包含一个区间的所有区间的交集实际上就是求 m a x ( l 1 ) , m i n ( r 1 ) max(l_1),min(r_1) max(l1),min(r1),然后做差就是交集大小。

先说求 m i n ( r 1 ) min(r1) min(r1),我们前面说了,可以排序+线段树维护 r 1 > r r_1>r r1>r的所有 r r r,然后线段树查 [ r , m x ] [r,mx] [r,mx]这个区间里的最小值就行了,这可以用一个权值线段树,存所有 r r r的出现次数,然后在 [ r , m x ] [r,mx] [r,mx]里找最小的非零位置就行了,这实际上是一个线段树二分。

当然后来我意识到,查询不小于某个值的最小值,实际上可以直接用set.lower_bound,这里做麻烦了

然后求 l 1 < = l l_1<=l l1<=l里的最大值,同理。

最后对于每个 [ l , r ] [l,r] [l,r]我们都可以求出 m a x ( l 1 ) , m i n ( r 1 ) max(l_1),min(r_1) max(l1),min(r1) m a x ( l 1 ) − m i n ( r 1 ) − ( r − l ) max(l_1)-min(r_1)-(r-l) max(l1)min(r1)(rl)即为答案

struct Tree{
	struct Node{
		int l,r,mx;
	}tr[N<<2];
	
	void pushup(int u){
		tr[u].mx=tr[ls].mx+tr[rs].mx;
	}
	
	void build(int u,int l,int r){
		tr[u]={l,r,0};
		if(l==r)	return;
		int mid=(l+r)>>1;
		build(ls,l,mid);	build(rs,mid+1,r);
		pushup(u);
	}
	
	void modify(int u,int idx,int val){
		if(tr[u].l==tr[u].r)	tr[u].mx+=val;
		else{
			int mid=(tr[u].l+tr[u].r)>>1;
			if(mid>=idx)	modify(ls,idx,val);
			else modify(rs,idx,val);
			pushup(u);	
		}
	}
	
	int query(int u,int l,int r){
		if(r<tr[u].l||tr[u].r<l)	return 0;
		if(l<=tr[u].l&&tr[u].r<=r)	return  tr[u].mx;
		return query(ls,l,r)+query(rs,l,r);	
	}
	int ask(int u,int l,int r){
		if(tr[u].l==tr[u].r)	return tr[u].l;
		else{
			int mid=(tr[u].l+tr[u].r)>>1;
			if(r<=mid)return ask(ls,l,r);
			if(l>mid)return ask(rs,l,r);
			int res=query(ls,l,r);
			if(res) return ask(ls,l,r);
			else return ask(rs,l,r);
		}
	}
	int ask1(int u,int l,int r){
		if(tr[u].l==tr[u].r)	return tr[u].l;
		else{
			int mid=(tr[u].l+tr[u].r)>>1;
			if(r<=mid)return ask1(ls,l,r);
			if(l>mid)return ask1(rs,l,r);
			int res=query(rs,l,r);
			if(res) return ask1(rs,l,r);
			else return ask1(ls,l,r);
		}
	}
}t;
void solve(){
	cin>>n;
	vi l(n+1),r(n+1),l1(n+1),r1(n+1);
	rep(i,1,n)cin>>l[i]>>r[i];
	
	vi all;
	rep(i,1,n){
		all.pb(l[i]);
		all.pb(r[i]);
	}
	sort(all.begin(),all.end());
	all.erase(unique(all.begin(),all.end()),all.end());
	
	unordered_map<int,int>lisan;
	rep(i,1,n){
		lisan[l[i]]=lower_bound(all.begin(),all.end(),l[i])-all.begin()+1;
		lisan[r[i]]=lower_bound(all.begin(),all.end(),r[i])-all.begin()+1;
	}
	
	map<int,vi>mp,mp1;
	rep(i,1,n){
		mp[l[i]].pb(i);
		mp1[r[i]].pb(i);
	}
	
	m=all.size();
	t.build(1,1,m);
	
	for(auto &[k,v]:mp){
		for(int id:v){
			t.modify(1,lisan[r[id]],1);
		}
		for(int id:v){
			t.modify(1,lisan[r[id]],-1);
			int sum=t.query(1,lisan[r[id]],m);
			if(!sum){
				t.modify(1,lisan[r[id]],1);
				continue;
			}
			int pos=t.ask(1,lisan[r[id]],m);
			r1[id]=all[pos-1];
			t.modify(1,lisan[r[id]],1);
		}
	}
	
	t.build(1,1,m);
	for(auto it=mp1.rbegin();it!=mp1.rend();++it){
		for(int id:it->second){
			t.modify(1,lisan[l[id]],1);
		}
		for(int id:it->second){
			t.modify(1,lisan[l[id]],-1);
			int sum=t.query(1,1,lisan[l[id]]);
			if(!sum){
				t.modify(1,lisan[l[id]],1);
				continue;
			}
			int pos=t.ask1(1,1,lisan[l[id]]);
			l1[id]=all[pos-1];
			t.modify(1,lisan[l[id]],1);
		}
	}
	rep(i,1,n){
		if(l1[i]&&r1[i]){
			cout<<r1[i]-l1[i]-(r[i]-l[i])<<'\n';
		}
		else{
			cout<<0<<'\n';
		}
	}
}

http://www.kler.cn/a/525827.html

相关文章:

  • Leetcode:219
  • Win11下帝国时代2无法启动解决方法
  • DeepSeek-R1本地部署笔记
  • Spring Boot - 数据库集成05 - 集成MongoDB
  • 程序地址空间
  • FLTK - FLTK1.4.1 - 搭建模板,将FLTK自带的实现搬过来做实验
  • unity学习24:场景scene相关生成,加载,卸载,加载进度,异步加载场景等
  • 前端进阶:深度剖析预解析机制
  • 电梯系统的UML文档13
  • 跟李沐学AI:视频生成类论文精读(Movie Gen、HunyuanVideo)
  • python学opencv|读取图像(五十一)使用修改图像像素点上BGR值实现图像覆盖效果
  • java求职学习day19
  • AI协助探索AI新构型的自动化创新概念
  • 8641 冒泡排序
  • 【教学类-89-03】20250113新年篇03——福字贴(PPTX艺术字-空心字)
  • 我的求职面经:(2)C++中空指针请使用nullptr不要使用NULL
  • Haproxy介绍及学习
  • 代码随想录_栈与队列
  • 1/30每日一题
  • 课题推荐:基于matlab,适用于自适应粒子滤波的应用
  • [权限提升] Windows 提权 — 系统内核溢出漏洞提权
  • 三路排序算法
  • 拼车(1094)
  • 在汇编语言中,ASSUME 是一个用于告诉汇编器如何将段寄存器与特定段名称关联的指令
  • AutoDL 云服务器:xfce4 远程桌面 终端乱码 + 谷歌浏览器
  • oracl:数据查询语言DQL