首页 > 其他分享 >CodeForces 1540D Inverse Inversions

CodeForces 1540D Inverse Inversions

时间:2024-03-05 12:55:06浏览次数:29  
标签:typedef Inverse int CodeForces long maxn Inversions define

洛谷传送门

CF 传送门

小清新题。

首先容易发现每个合法的 \(b\) 唯一对应一个排列,大概就是每个时刻排列元素的相对顺序,然后插入到相应的位置。

但是这样太麻烦了。发现题目只要求求单点的 \(p\) 值。这应该有更简单的方法。

考虑令 \(b_i \gets i - b_i\) 表示 \(p_i\) 在前缀 \([1, i]\) 的排名。那么我们时刻维护 \(p_i\),然后遍历 \(i + 1\) 到 \(n\),若 \(b_i \le p\) 那么令 \(p \gets p + 1\)。这样我们得到了一个 \(O(nq)\) 的做法。

一种优化方向是分块。预处理出每个块每个数经过后会变成什么。设 \(x\) 经过后变成 \(f_x\)。容易发现 \(f\) 的值域为 \([1, len]\),也就是说它是一个 \(1 \sim len\) 的分段函数。那么求出每一段的断点就可以二分求出一个数经过这个块后会增加多少。

考虑如何对一个块预处理 \(f_x\)。相当于每次找到第一个 \(a_i + i \ge k\) 的位置 \(i\),然后对 \([i, n]\) 加 \(1\)。容易树状数组维护,找到第一个位置可以树状数组上二分。

这样全部找到的位置就是分段函数的断点。

时间复杂度 \(O(n \sqrt{n} \log n)\)。

code
// Problem: D. Inverse Inversions
// Contest: Codeforces - Codeforces Round 728 (Div. 1)
// URL: https://codeforces.com/problemset/problem/1540/D
// Memory Limit: 512 MB
// Time Limit: 5000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include <bits/stdc++.h>
#define pb emplace_back
#define fst first
#define scd second
#define mkp make_pair
#define mems(a, x) memset((a), (x), sizeof(a))

using namespace std;
typedef long long ll;
typedef double db;
typedef unsigned long long ull;
typedef long double ldb;
typedef pair<ll, ll> pii;

const int maxn = 100100;

int n, m, a[maxn], blo, bel[maxn], L[maxn], R[maxn], f[330][330];

struct BIT {
	int c[maxn];
	
	inline void update(int x, int d) {
		for (int i = x; i <= n; i += (i & (-i))) {
			c[i] += d;
		}
	}
	
	inline int find(int x) {
		int p = 0, s = 0;
		for (int i = 16; ~i; --i) {
			if (p + (1 << i) <= n && s + c[p + (1 << i)] < x) {
				s += c[p += (1 << i)];
			}
		}
		return p + 1;
	}
} B;

inline void build(int x) {
	for (int i = L[x]; i <= R[x]; ++i) {
		int p = B.find(a[i]);
		B.update(p, 1);
		f[x][i - L[x] + 1] = p;
	}
	sort(f[x] + 1, f[x] + R[x] - L[x] + 2);
	for (int i = 1; i <= R[x] - L[x] + 1; ++i) {
		B.update(f[x][i], -1);
	}
}

void solve() {
	scanf("%d", &n);
	blo = sqrt(n);
	for (int i = 1; i <= n; ++i) {
		scanf("%d", &a[i]);
		B.update(i, 1);
		a[i] = i - a[i];
		bel[i] = (i - 1) / blo + 1;
		if (!L[bel[i]]) {
			L[bel[i]] = i;
		}
		R[bel[i]] = i;
	}
	for (int i = 1; i <= bel[n]; ++i) {
		build(i);
	}
	scanf("%d", &m);
	while (m--) {
		int op, x, y;
		scanf("%d%d", &op, &x);
		if (op == 1) {
			scanf("%d", &y);
			a[x] = x - y;
			build(bel[x]);
		} else {
			int p = a[x];
			for (int i = x + 1; i <= R[bel[x]]; ++i) {
				p += (a[i] <= p);
			}
			for (int i = bel[x] + 1; i <= bel[n]; ++i) {
				int t = upper_bound(f[i] + 1, f[i] + R[i] - L[i] + 2, p) - f[i] - 1;
				p += t;
			}
			printf("%d\n", p);
		}
	}
}

int main() {
	int T = 1;
	// scanf("%d", &T);
	while (T--) {
		solve();
	}
	return 0;
}

标签:typedef,Inverse,int,CodeForces,long,maxn,Inversions,define
From: https://www.cnblogs.com/zltzlt-blog/p/18053780

相关文章

  • Codeforces edu 156 C题
    https://codeforces.com/contest/1886/problem/C思路这道题的核心问题是:给你一个字符串s,你要删除k个字母,你要找出删除k个字母后字典序最小的s。为了使字典序最小,我们就应该把字符串删成递增的样子stringtmp="";//tmp用来存删完后的字符串s+='$';//s的末尾加一个比'......
  • Educational Codeforces Round 162 E 点分治 虚树 树形dp
    传送门给出\(n\le2\cdot10^5\)的一棵树,每个节点有一个颜色。求出路径长度为\(2\)路径首端和尾端拥有相同颜色,且路径上其他点不存在相同颜色的点的路径条数。当时看错题了,把颜色抽出来后没法做了。后来感觉能点分治,然后把题看对了,遂写了一个极其抽象的点分治。除此之外,把某......
  • Codeforces Round 930 (Div. 1) C dij 建图
    离较好的方法差一点。考虑到了可以按照枚举属性并按照当前属性从小到大排序,这样可以从一个点到大另一个点。设当前在排序序列中点为\(i\)当\(i\)走向\(k,i>=k\)需要支付\(c_k\)的代价。而\(i\)到\(k,i<k\)则需\(k-i+c_k\)的代价。则对于不同的\(i\)由于代价没有连续性,当时想......
  • Codeforces Round 892 (Div. 2)
    \[\large\text{Round7:CodeforcesRound892(Div.2)(VP)}\]一言:所谓人,无论是谁到了最后,都会形单影只。——悠久之翼2最令人无语的是最后三分钟交代码的时候把\(\text{D}\)题交到了\(\text{E}\)题,结果能过的代码直接没有过。。\(\text{D:AndreyandEscapefr......
  • Educational Codeforces Round 120
    \[\large\text{Round1:EducationalCodeforcesRound120(VP)}\]一言:孤独的人不会伤害别人,只会不断地伤害自己罢了。——我的青春恋爱物语果然有问题\(\text{C:SetorDecrease}\)后四题唯一场切题,(别问我为什么只有这一道)。读完题之后,理一下思路,可以很容易的想到......
  • Codeforces Round 893 (Div. 2)
    \[\large\text{Round3:CodeforcesRound893(Div.2)(VP)}\]一言:从你站在桥上看我的那一刻起你就是我的世界——火影忍者不是很满意,还是没有突破\(\text{D}\)题,确实是没有想到这题竟然如此毒瘤。。\(\text{D:TreesandSegments}\)首先不难想到一种思路,就是枚举......
  • Codeforces Round 806 (Div. 4) A-G(补题)
    A.YESorYES?思路:一次判断三个字母是否是y、e、s的大小写即可。这题是很久前写的,哈哈,马蜂改了不少。。#include<bits/stdc++.h>usingnamespacestd;intn;chars[5];intmain(){ scanf("%d",&n); for(inti=1;i<=n;i++){ scanf("%s",s+1); if......
  • 16 Educational Codeforces Round 142 (Rated for Div. 2)C. Min Max Sort(递归、思维
    C.MinMaxSort很不错的一道题目,不过脑电波和出题人每对上,\(qwq。\)正难则反。我们考虑最后一步是怎么操作的。最后一步一定是对\(1\)和\(n\)进行操作那么上一步呢?上一步应该是对\(2\)和\(n-1\)以此类推第一步应该是对\(\frac{n}{2}\)和\(\frac{n}{2}+1\)我们的答案应该......
  • Educational Codeforces Round 143 (Rated for Div. 2)C. Tea Tasting(前缀和+二分、
    C.TeaTasting思路这里枚举有三种思路然后经过考虑3是最可行的,然后接着考虑如何计算贡献这里在实现的时候用了一个差分数组,因为我们需要记录第i个茶师它喝了多少个\(b_i\)以及不满\(b_i\)的用\(c_i\)记录,最后计算一下答案即可。#include<bits/stdc++.h>#defineintlon......
  • Codeforces Round 930 (Div. 2)
    目录写在前面ABCDEF写在最后写在前面比赛地址:https://codeforces.com/contest/1937。被交互杀死的一集。赛时卡C明天有早八就直接睡大觉了,第二天看看D一眼秒了,最困的一集。A签到发现1会被先后交换到2,4,8,16……输出\(2^{\left\lfloor\logn\right\rfloor}\)即可。......