首页 > 其他分享 >CF848C Goodbye Souvenir

CF848C Goodbye Souvenir

时间:2024-07-23 20:42:25浏览次数:9  
标签:pre suf ++ CF848C Souvenir int cdq Goodbye define

CF848C Goodbye Souvenir

cdq分治求动态二维数点

先考虑答案,对于一种颜色 \(c\),假设出现位置集合为 \(S\),每个位置的前继记为 \(pre_i\),那么可以写成:

\[\sum\limits_{i\in S|pre_i\ge L|i\le R} i-pre_i \]

如果不修改,可以看到题目求的就是矩形横坐标 \([1,R]\) 到纵坐标 \([L,n]\) 的矩形中 \((i,pre_i)\) 的点的权值和,每个点的权值形如 \(i-pre_i\)。可以用静态二维数点完成。

加了修改,我们只需要加入一维静态的时间戳,就可以将动态二维数点问题转化为三维偏序,那么可以用 cdq 分治完成。

但是这题我最想说的其实是预处理时查询前继后继问题。可以用 set 维护,用指针可以轻松查找位置,我不会。

复杂度 \(O(n\log^2n)\)。

#include <bits/stdc++.h>
#define pii std::pair<int, int>
#define mk std::make_pair
#define fi first
#define se second
#define pb push_back

using i64 = long long;
using ull = unsigned long long;
const i64 iinf = 0x3f3f3f3f, linf = 0x3f3f3f3f3f3f3f3f;
/*

*/
const int N = 1e5 + 10;
i64 n, q, m, cnt;
std::set<int> S[N];
struct node {
	i64 x, y, op, f;
} a[N << 3];
bool cmp(node a, node b) {
	return a.x < b.x;
}
i64 c[N], ans[N], b[N];
int lowbit(int x) {return x & (-x);}
void add(int x, i64 y) {
	for(int i = x; i <= n; i += lowbit(i)) b[i] += y;
}
i64 qry(int x) {
	i64 ret = 0;
	for(int i = x; i; i -= lowbit(i)) ret += b[i];
	return ret;
} 
void cdq(int l, int r) {
	if(l == r) return;
	int mid = (l + r) >> 1;
	cdq(l, mid), cdq(mid + 1, r);
	std::sort(a + l, a + mid + 1, cmp), std::sort(a + mid + 1, a + r + 1, cmp);
	int ls = l;
	for(int i = mid + 1; i <= r; i++) {
		if(a[i].op) {
			while(ls <= mid && a[ls].x <= a[i].x) {
				if(!a[ls].op) add(a[ls].y, (a[ls].x - a[ls].y) * a[ls].f);
				ls++;
			}
			ans[a[i].op] += qry(n) - qry(a[i].y - 1);
		}
	}
	for(int i = l; i < ls; i++) {
		if(!a[i].op) add(a[i].y, -(a[i].x - a[i].y) * a[i].f);
	}
}
int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    
	std::cin >> n >> q;

	for(int i = 1; i <= n; i++) {
		std::cin >> c[i];
		if(S[c[i]].size()) {
			a[++m] = {i, *S[c[i]].rbegin(), 0, 1};
		}
		S[c[i]].insert(i);
	}

	for(int i = 1; i <= q; i++) {
		int op, l, r;
		std::cin >> op >> l >> r;
		if(op == 2) a[++m] = {r, l, ++cnt, 0};
		else {
			auto p = S[c[l]].find(l);
			int pre = 0, suf = 0;
			if(p != S[c[l]].begin()) {
				a[++m] = {l, pre = *--p, 0, -1}, ++p;
			}
			if(++p != S[c[l]].end()) {
				a[++m] = {suf = *p, l, 0, -1};
			}
			if(pre && suf) {
				a[++m] = {suf, pre, 0, 1};
			}
			S[c[l]].erase(l);

			S[c[l] = r].insert(l); 
			p = S[c[l]].find(l), pre = suf = 0;
			if(p != S[c[l]].begin()) {
				a[++m] = {l, pre = *--p, 0, 1}, ++p;
			}
			if(++p != S[c[l]].end()) {
				a[++m] = {suf = *p, l, 0, 1};
			}
			if(pre && suf) {
				a[++m] = {suf, pre, 0, -1};
			}
		}
	}

	cdq(1, m);

	for(int i = 1; i <= cnt; i++) std::cout << ans[i] << "\n";

	return 0;
}

标签:pre,suf,++,CF848C,Souvenir,int,cdq,Goodbye,define
From: https://www.cnblogs.com/FireRaku/p/18319582

相关文章

  • CAD Exchanger SDK 3.24.0 终极版-say goodbye
    随着今年即将结束,还有一件重要的事情——CADExchanger3.24.0的发布。此次最新更新带来了一系列虽小但仍然值得注意的改进。其中包括ManufacturingToolkit(MTK)和Unity增强功能、Lab和VisualizationToolkit中模型部件检测的改进以及WebToolkit(WTK)中的修复。......
  • D - Souvenirs
    D-Souvenirshttps://atcoder.jp/contests/abc358/tasks/abc358_d 思路贪心算法。把a数组和b数组从小到大排序。遍历b数组的每一个元素bi,在a数组中找到第一个大于等于bi元素,累加值。 Codehttps://atcoder.jp/contests/abc358/submissions/54656383#defineintlong......
  • 20240504 —— Goodbye 2024(1/3).
    很久没有用心写过随笔了。写随笔对我来说是个很困难的事情,因为我文笔烂完了。每次都是写前觉得有一堆东西可以写,写的时候就不知道咋连结在一起,最后乱写了一堆发出来。2024/5/422:39看了会物理书后累了打了会块(TETR.IO),3:5,DEFEAT。怎么回事呢。打完前两局感觉对手硬实力不是......
  • 洛谷题解-[ABC286E] Souvenir
    https://www.luogu.com.cn/problem/AT_abc286_e题目描述NNN個の都市があり、いくつかの相異なる都市の間は一方通行の直行便によって移動することができます。どの直行便が存在するかはNNN個の長さNNNの文字列S1,S2,…,SNS_1,S_2,\ldots,S_NS1​,S2​,…,SN​......
  • CF765F Souvenirs 题解
    题目链接:CF或者洛谷想了很久,然后想起做过的一道题:秃子酋长,一开始以为差不多,结果写着写着就发现不对劲了。最后写出了个神仙回滚莫队解法,感觉很妙,记录下。进入神仙分析时刻首先,我们来考虑一个事实,加上一个数以后,如果能找到它的前后驱,那么可以立马更新最优解,这个也即是瓶颈点。......
  • Goodbye2023
    GoodBye2023A2023题目描述给定n个数,让我们判断是否能与m个数相乘后可以得到2023,并且将这些数输出出来解题思路我们只需要判断这些数能否被2023整除。代码#include<bits/stdc++.h>#defineintlonglong#defineendl'\n'#definefix(n)std::fixed<<std::......
  • 2023 Goodbye!
    摆了一天,终于想起今天该跨年了(虽然那个时候我可能还在教室里),该写点什么。可是真的打开文档,却发现倏忽而过的2023好像并没有给我留下什么深刻的印象。那就浅浅地用最后三天的生活总结这一年吧。2023.12.31今天推掉了父母约出去和亲戚吃饭的事,一方面作业很多,另一方面一天的假期......
  • CF765F. Souvenirs
    压位trie好厉害。显然加一个数很好维护,删一个数有点不好做,考虑回滚莫队。用平衡树维护数的集合,每次插入之前用前驱/后继与插入数的差更新一下答案,可以\(O(n\sqrt{n}\logn)\),会Timelimitexceededontest7or8。看上去我们已经优化到极限了,怎么办呢?显然莫队的\(n\sqrt{......
  • 洛谷P9035 Pont des souvenirs 题解
    题面很简洁,这里不做多说。70pts做法首先考虑到\(a_{n-1}\)和\(a_n\)两项是整个数列\(a\)中的最大的两项,所以若\(a_{n-1}+a_n\)不超过\(k+1\),则数列中任意两项......
  • CF765F Souvenirs 题解
    Preface在会压位Trie的前提下,本题最好想的做法应该是压位Trie+回滚莫队,可是竟然没人写这个做法的题解?Solution我们先转化题意:设\(a_i\)在\([l,r]\)中的前驱后继......