首页 > 其他分享 >CodeForces 1060G Balls and Pockets

CodeForces 1060G Balls and Pockets

时间:2023-11-02 19:00:29浏览次数:52  
标签:qq typedef Balls ll 位置 CodeForces long Pockets BIT

洛谷传送门

CF 传送门

NOIP 模拟赛 T2。很厉害的题。

想象数轴上 \(a_1, a_2, \ldots, a_n\) 位置上各有一个洞,每个非负整数位置上有一个点。

每次操作相当于,对于每个点,如果它刚好位于一个洞,那么它会掉进去;否则设它的位置为 \(p\),位置在它前面的洞有 \(t\) 个,那么这个点的位置变成 \(p - t\)。容易发现每时刻每个点的位置互不相同。

一次询问 \((x, k)\) 相当于,进行 \(k\) 次操作后,找到数轴上位置为 \(x\) 的点,求它进行所有操作前的位置。

单点的移动没有很好的性质。考虑一段连续点的移动。比如极远处 \(L = 10^{18}\) 有一段连续点 \([L, L + n - 1]\);那么容易发现这些点不重不漏地经过 \([a_1, L + n - 1]\) 的位置。并且每一时刻连续点都是一段连续的区间。

发现对于一个 \([a_i, a_{i + 1})\) 段内的移动,连续点的区间 \([L, L + i - 1]\) 只会重复地进行 \(L \gets L - i\) 的变化,直到连续点覆盖了 \(a_i\)。那么我们只需要维护当连续点的区间覆盖了一个洞时连续点的变化(有哪些点掉洞里了)。

对于一个询问 \((x, k)\),设在 \(t\) 时刻连续点覆盖了 \(x\),就相当于求它 \(t - k\) 时刻的位置。

那么每个询问都可以被转化成,初始位于 \(L + x\) 的点,求它 \(k\) 时刻的位置。询问全部离线下来按 \(k\) 从小到大排序,直接模拟一遍即可。

使用树状数组维护初始 \([L, L + n - 1]\) 的连续点哪些掉洞里了。

时间复杂度 \(O((n + m) \log n)\)。

code
// Problem: G. Balls and Pockets
// Contest: Codeforces - Codeforces Round 513 by Barcelona Bootcamp (rated, Div. 1 + Div. 2)
// URL: https://codeforces.com/problemset/problem/1060/G
// Memory Limit: 512 MB
// Time Limit: 2000 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;

ll n, m, a[maxn], ans[maxn];

namespace BIT {
	ll c[maxn];
	
	inline void init() {
		mems(c, 0);
	}
	
	inline void update(ll x, ll d) {
		for (int i = x; i <= n; i += (i & (-i))) {
			c[i] += d;
		}
	}
	
	inline ll query(ll x) {
		ll res = 0;
		for (int i = x; i; i -= (i & (-i))) {
			res += c[i];
		}
		return res;
	}
	
	inline ll kth(ll k) {
		ll s = 0, p = 0;
		for (int i = (1 << __lg(n)); i; i >>= 1) {
			if (p + i <= n && s + c[p + i] < k) {
				p += i;
				s += c[p];
			}
		}
		return p + 1;
	}
}

struct node {
	ll x, k, id;
} qq[maxn];

void solve() {
	scanf("%lld%lld", &n, &m);
	mems(ans, -1);
	for (int i = 1; i <= n; ++i) {
		scanf("%lld", &a[i]);
		BIT::update(i, 1);
	}
	for (int i = 1; i <= m; ++i) {
		scanf("%lld%lld", &qq[i].x, &qq[i].k);
		qq[i].id = i;
		if (qq[i].x < a[1]) {
			ans[i] = qq[i].x;
		}
	}
	sort(qq + 1, qq + m + 1, [&](const node &a, const node &b) {
		return a.x > b.x;
	});
	ll l = 1e18, t = 0;
	for (int i = 1, j = n; i <= m && j;) {
		ll d = (l - a[j] + j - 1) / j;
		ll k = d * j;
		while (i <= m && qq[i].x >= l - k) {
			if (ans[qq[i].id] != -1) {
				++i;
				continue;
			}
			qq[i].k = t + (l - qq[i].x + j - 1) / j - qq[i].k;
			qq[i].x = BIT::kth(qq[i].x - (l - (l - qq[i].x + j - 1) / j * j) + 1);
			++i;
		}
		while (j && a[j] >= l) {
			ll t = BIT::kth(a[j] - l + 1);
			BIT::update(t, -1);
			--j;
		}
		l -= k;
		t += d;
	}
	BIT::init();
	for (int i = 1; i <= n; ++i) {
		BIT::update(i, 1);
	}
	sort(qq + 1, qq + m + 1, [&](const node &a, const node &b) {
		return a.k < b.k;
	});
	l = 1e18;
	t = 0;
	for (int i = 1, j = n; i <= m && j;) {
		ll d = (l - a[j] + j - 1) / j;
		ll k = d * j;
		while (i <= m && qq[i].k <= t + d) {
			if (ans[qq[i].id] != -1) {
				++i;
				continue;
			}
			ans[qq[i].id] = l - 1 + BIT::query(qq[i].x) - (qq[i].k - t) * j;
			++i;
		}
		while (j && a[j] >= l) {
			ll t = BIT::kth(a[j] - l + 1);
			BIT::update(t, -1);
			--j;
		}
		l -= k;
		t += d;
	}
	for (int i = 1; i <= m; ++i) {
		printf("%lld\n", ans[i]);
	}
}

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

标签:qq,typedef,Balls,ll,位置,CodeForces,long,Pockets,BIT
From: https://www.cnblogs.com/zltzlt-blog/p/17806062.html

相关文章

  • Educational Codeforces Round 134 (Div.2) D 题解
    题目链接D.MaximumAND题目大意给定两组序列\(a\)\(b\),长度为\(n\),现有一新序列\(c\),长度也为\(n\)。其中,\(c_i=a_i\oplusb_i\)。定义\(f(a,b)=c_1\&c_2\&……\&c_n\)。现在你可以随意编排\(b\)序列的顺序,求\(f(a,b)\)的最大值。思路以下位运算均是......
  • Educational Codeforces Round 128 (Rated for Div. 2)
    添加链接描述C题显然二分0的数量,然后双指针,算一下前缀和后缀1的数量即可。#include<cstdio>#include<algorithm>#include<cstring>#include<cmath>#include<map>#include<vector>#include<set>#defineAputs("YES")#defineBputs("NO&q......
  • Codeforces Round 906 (Div. 2)
    CodeforcesRound906(Div.2)比赛链接A.Doremy'sPaint3题目链接判断给定的数组是不是满足a1+a2=a2+a3=a3+a4=......=an-1+anA思路:这个题一开始没有读仔细问题,导致一时间出错了,后来读清楚问题之后发现其实这个数组中只能出现两个数字,且两个数字之间的差值最多是1A代码:......
  • Codeforces Round 907 (Div. 2) B. Deja Vu(二分+后缀和+位运算)
    CodeforcesRound907(Div.2)B.DejaVu思路:预处理31位的\(2^x\)存在\(tmp_i\)对于输入\(a_i\),通过查找最后一个二进制1位置,存在\(x0_i\)由题意可知,对于输入的\(x\),如果有\(a_i\)可整除\(x\),则会使\(a_i\)加上\(2^{x-1}\)所以之后除非是\(x-1\),否则无效,因此把输入\(x\)......
  • Codeforces Round 907 (Div. 2)
    CodeforcesRound907(Div.2)A.SortingwithTwos题意:给一个长度为n的数组,可以做任意次以下操作:选择一个整数m,将1-2m的数减1。若能使数组变为一个单调递增的数组则输出YES,否则输出NO分析:只需要保证2m+1-2m+1单调递增即可代码:#include<bits/stdc++.h>usingnamespace......
  • Codeforces Round 906 Div. 1 (CF1889)
    貌似现在发周六的CF题解已经失去了时效性,不过问题不大。A.QingshanLovesStrings2Description定义一个长度为\(k\)的\(01\)串\(s\)是好的,当且仅当\(\foralli\in[1,k],s_i\neqs_{k-i+1}\)。现给你一个串,每次操作你可以在任意位置插入一对\(01\)。请构造操作方......
  • Codeforces Round 906 (Div. 2)A-E1
    A.Doremy'sPaint3记数组中数的种类数为\(k\),当\(k=1\)时,答案为\(yes\);当\(k=2\)时,记两个种类的数的个数差为\(d\),当\(d≤1\)时,答案为\(yes\);其他情况答案为\(no\)。时间复杂度:\(O(nlogn)\)1voidsolve()2{3intn;cin>>n;45map<int,int>mp;6......
  • Codeforces Round 895
    提炼感觉这种题还是很金典的我们看到乘积就应该想到其很容易爆而我们省1的话也最多就是2e5数量级的我们为了省事不用算上界可以直接把这个上界设为1e9也不会爆LL只要乘积突破这个上界我们就肯定要是有旁边的大于1的数我们都要吃掉因为增量都超过了1e9那么多我们只要......
  • codeforces 1829G. Hits Different 容斥原理+记忆化搜索
    题目描述:给定一个n,把n给打倒,然后递归的求出包含n在内的上面所有的会倒下的瓶子值的平方和。这里使用二分先求出目前给定的n的行号i和列号j。观察可以发现,对于所有的列号j,j=1或者j=i时,是需要考虑往上单边的总和,其他情况都有两个分支。再观察可以发现,两个分支在再上一行的重合部......
  • CodeForces 1246F Cursor Distance
    洛谷传送门CF传送门发现一个性质:能跳不超过\(j\)步到达\(i\)的所有点形成一段区间。设这这段区间为\([L_{i,j},R_{i,j}]\)。那么答案即为:\[\sum\limits_{i=1}^n\sum\limits_{j=0}n-R_{i,j}+L_{i,j}-1\]并且:\[[L_{i,j},R_{i,j}]=\bigcup\limits_......