首页 > 其他分享 >CF101234A Hacker Cups and Balls【二分+线段树】

CF101234A Hacker Cups and Balls【二分+线段树】

时间:2023-06-01 18:47:34浏览次数:44  
标签:Hacker Balls lc CF101234A sum mid int tag rc

Description

给一个长度为 n 的排列,对它做 m 次操作,每次对 [l, r] 区间内进行升序/降序排序。

问最后的序列处于最中心的数是多少(n为奇数)。

Solution

是一类没有写过的题,参考题解

二分答案,对于当前的 mid ,将大于等于 mid 的数设置为 1,小于 mid 的数设置为 0。这样一来,叶结点的值只有 0/1,区间操作时也可以直接对部分区间赋值为 1,部分区间赋值为0。最后单点查询中间值是否为1即可。

具体来说,对于一次升序的区间操作 [l,r],先建树,并且查询其中1的数目sum。将[r-sum+1, r]的区间赋值为 1 ,[l, r-sum] 赋值为0。注意判断区间的合法性(\(l\leq r\))。降序操作类似。

所以,我们需要支持的线段树操作只有区间求和、区间修改(改为0/1)。

关于 tag 的设置:为了方便,tag = 0 代表该区间需要全部覆盖为0,tag = 1代表该区间需要全部覆盖为1,tag = -1表示无需pushdown。

Code

// By DTTTTTTT 2023/6/1 六一快乐!
/*
* dtt每次都写错的线段树易错点小结:
* 1. 计算mid的时候只有build中是直接使用 l+r>>1,update和query中都是 t[p].l+t[p].r>>1;
* 2. update的末尾记得 t[p].sum=t[lc].sum+t[rc].sum
* 3. update和query的 l 与 r 是不需要改变/收缩范围的,如果改变需要讨论,会很容易错
* 4. pushdown中记得写直接return的两种情况(叶结点、没有tag)
* 
* 小结一下线段树的各个操作流程:
* 1. build(int p,int l,int r):
	建树,需要初始化node的l/r/tag,叶结点直接赋sum并返回,非叶结点继续向下建树,建完后累加sum。
* 2. query(int p,int l,int r):
	若p结点的区间完全被涵盖在[l,r]区间中,直接返回其sum;
	否则需要向下计算,先pushdown,然后分别看左右两个子区间是否与[l,r]有重合,有则需计算。
	int ret=0, mid=t[p].l+t[p].r>>1;
	if(l<=mid) ret+=query(p<<1,l,r); //这里的l与r无需改变
	if(r>mid) ret+=query(p<<1|1,l,r); 
	return ret;
* 3. update(int p,int l,int r,int val)://这里以将[l,r]区间内所有数变为val这个更新操作为例
	若p结点的区间完全被涵盖在[l,r]区间中,直接更新sum并标记tag;
	否则需要向下更新,先pushdown,然后分别看左右两个子区间是否与[l,r]有重合,有则需更新。
	最后一定记得更新当前结点的sum。
	int mid=t[p].l+t[p].r>>1;
	if(l<=mid) update(p<<1,l,r,val);
	if(r>mid) update(p<<1|1,l,r,val);
	t[p].sum=t[p<<1].sum+t[p<<1|1].sum;
* 4. pushdown(int p):只需pushdown一层,无需递归操作
	首先判断无需pushdown的情况:叶结点或者没有打lazy_tag
	判断完毕后更新两个子区间的sum和tag
	最后一定记得将自己的tag取消
	t[p<<1].sum =..... ,t[p<<1|1].sum=...,t[p<<1].tag=t[p<<1|1].tag=t[p].tag;
	t[p].tag = -1; //假设这里-1代表没有

	其实觉得query和update的操作特别像,都是若全都包含在内则直接处理并返回,不然就要向下走。
	特别注意的是update向下更新完毕后记得更新自己的sum。
*/
#include<iostream>
#define lc (p<<1)
#define rc (p<<1|1)
using namespace std;
const int N = 1e5 + 5;
int n, m, a[N], b[N];
struct interval {
	int l, r, op;
}inte[N];
struct node {
	int l, r, sum, tag;
}t[N << 2];
void build(int p, int l, int r) {
	t[p].l = l, t[p].r = r, t[p].tag = -1;
	if (l == r) {
		t[p].sum = b[l];
		return;
	}
	int mid = l + r >> 1;
	build(lc, l, mid);
	build(rc, mid + 1, r);
	t[p].sum = t[lc].sum + t[rc].sum;
}
void pushdown(int p) {
	if (t[p].l == t[p].r || t[p].tag == -1) //无需pushdown的两种情况
		return;
	t[lc].tag = t[rc].tag = t[p].tag;
	t[lc].sum = (t[lc].r - t[lc].l + 1) * t[p].tag;
	t[rc].sum = (t[rc].r - t[rc].l + 1) * t[p].tag;
	//t[p].sum = t[lc].sum + t[rc].sum; 这里可以没有
	t[p].tag = -1;
}
int query(int p, int l, int r) {
	if (t[p].l >= l && t[p].r <= r)
		return t[p].sum;
	pushdown(p);
	int mid = t[p].l + t[p].r >> 1, ret = 0;
	//永远都会写错成 mid=l+r>>1 啊啊啊!!!!!!!rem!!!
	if (l <= mid)
		ret += query(lc, l, r); //这里的l与r无需改变
	if (r > mid)
		ret += query(rc, l, r);
	return ret;
}
void update(int p, int l, int r, int val) {
	if (l > r)
		return;
	if (t[p].l >= l && t[p].r <= r) {
		t[p].sum = (t[p].r - t[p].l + 1) * val;
		t[p].tag = val;
		return;
	}
	pushdown(p);
	int mid = t[p].l + t[p].r >> 1;
	if (l <= mid)
		update(lc, l, r, val);
	if (r > mid)
		update(rc, l, r, val);
	t[p].sum = t[lc].sum + t[rc].sum; //这里不能落
}
bool check(int mid) {
	for (int i = 1;i <= n;++i)
		b[i] = (a[i] >= mid);
	build(1, 1, n);
	for (int i = 1;i <= m;++i) {
		int l = inte[i].l, r = inte[i].r, op = inte[i].op;
		int sum = query(1, l, r);
		if (op == 1) //升序
			update(1, l, r - sum, 0), update(1, r - sum + 1, r, 1);
		else
			update(1, l, l + sum - 1, 1), update(1, l + sum, r, 0);
	}
	return query(1, n / 2 + 1, n / 2 + 1);
}
int main() {
	ios_base::sync_with_stdio(false), cin.tie(0), cout.tie(0);

	cin >> n >> m;
	for (int i = 1;i <= n;++i) cin >> a[i];
	for (int i = 1;i <= m;++i) {
		cin >> inte[i].l >> inte[i].r;
		if (inte[i].l > inte[i].r)
			swap(inte[i].l, inte[i].r), inte[i].op = 2; //降序
		else
			inte[i].op = 1; //升序
	}

	int l = 1, r = n, mid, ans = -1;
	while (l <= r) {
		mid = l + r >> 1;
		if (check(mid)) 
			ans = mid, l = mid + 1;
		else 
			r = mid - 1;
	}

	cout << ans << endl;

	return 0;
}

标签:Hacker,Balls,lc,CF101234A,sum,mid,int,tag,rc
From: https://www.cnblogs.com/dttttttt/p/17449884.html

相关文章

  • CF1728A Colored Balls: Revisited题解
    去我的Blog观看修改时间:2022/9/11修改了格式与标点修改时间:2022/9/13修改了个别不严谨的语句题目大意有\(n\)种颜色的球,颜色为\(i\)的球为\(cnt_i\)个(\(cnt_1+cnt_2+\dots+cnt_n\)为奇数)。每次从球堆中取出\(2\)个颜色不相同的球,问最后可能剩下哪种颜色的球(输出任意......
  • [ABC132D] Blue and Red Balls
    2023-01-16题目传送门翻译难度&重要性(1~10):3题目来源AtCoder题目算法dp解题思路因为蓝球的数量是固定的,题目让我们求,在取\(i\)次的情况下,有几种方案,首先我们肯定要枚举\(i\),范围就是\(\sum_{i=1}^{k}\)了,然后因为他每次只能取连续的蓝球,于是我们就可以想到用插板......
  • Vulnhub之 BoredHackerBlog: Social Network 2.0靶机详细测试过程
    Socnet作者:jasonhuawen靶机信息名称:BoredHackerBlog:SocialNetwork2.0地址:https://www.vulnhub.com/entry/boredhackerblog-social-network-20,455/识别目标主机IP地址(kali㉿kali)-[~/Desktop/Vulnhub/Socnet]└─$sudonetdiscover-ieth1-r192.168.56.0/24Cu......
  • Hackers' Crackdown UVA11825
    你需要将n个集合分成尽量多组,使得每一组里面所有集合的并集等于全集  32122022014111013120   f[S]=max(f[S],f[S-j]+1)且j是一个包含所有点的集合#include<iostream>#include<algorithm>#include<cstring>usingname......
  • Uva--679 Dropping Balls(二叉树的编号)
    记录23:282023-4-16https://onlinejudge.org/external/6/679.pdfreference:《算法竞赛入门经典第二版》例题6-6二叉树,这里是完全二叉树,使用模拟的方式应该会TLE(虽然我用模拟的方式也TLE了,但不是这个原因,下面会提到原因)不用模拟的方式,转换思路,使用递归的方式去思考。这里......
  • Vulnhub之BoredHackerBlog: Social Network_Medium Socnet详细测试过程(拿到root shell
    BoredHackerBlog:SocialNetwork作者:jasonhuawen靶机信息名称:BoredHackerBlog:SocialNetwork地址:https://www.vulnhub.com/entry/boredhackerblog-social-network,454/识别目标主机IP地址Currentlyscanning:Finished!|ScreenView:UniqueHosts......
  • [CF755G] PolandBall and Many Other Balls 题解
    [CF755G]PolandBallandManyOtherBalls题解题意概括有一排\(n\)个球,定义一个组可以只包含一个球或者包含两个相邻的球。现在一个球只能分到一个组中,求从这些球中......
  • C - Roads and Libraries HackerRank - torque-and-development 【 并查集 】
    C-RoadsandLibraries HackerRank-torque-and-development 题意:给一堆点与点之间有没有边,在某一些地方建图书馆,最后让每个城市都可以到达有图书馆的地方,每个点......
  • The Origin of Cross-Site Scripting (XSS) - Hacker Etymology
    Cross-siteScriptingisthenameforawell-knowntypeofsecurityissuethatcanaffectwebsites.andIAlwaysthoughtthenameXssisterribleIthinkit'scon......
  • 【题解】CF850F Rainbow Balls
    整体方向很常规,但是最后的处理比较仙,记一下。思路期望dp.首先意识到最终会变成同一种颜色,并且不同颜色的期望步数不同。考虑到\(n\leq2.5\times10^3\),考虑钦定最......