2022年多校冲刺NOIP联训测试13 && 51nod2023省选联训 第三场

A 隔离

二分答案,简单\(check\)一下即可

code
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<queue>
#include<vector>
#include<set>
#include<map>
#include<iostream>
#include<random>

using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;

const int maxn = 100005;
inline ll read(){
	ll x = 0; char c = getchar();
	while(c < '0' || c > '9')c = getchar();
	do{x = (x << 3) + (x << 1) + (c ^ 48); c = getchar();}while(c <= '9' && c >= '0');
	return x;
}
int n, m;
struct node{ll l, r;}d[maxn];
bool cmp(node x, node y){return x.l < y.l;}
bool check(ll mid){
	ll las = -1e18;
	int p = 1;
	for(int i = 1; i <= n; ++i){
		while(p <= m && d[p].r < las + mid)++p;
		if(p > m)return false;
		las = max(las + mid, d[p].l);
	}
	return true;
}
int main(){
	n = read(), m = read();
	for(int i = 1; i <= m; ++i)d[i].l = read(), d[i].r = read();
	sort(d + 1, d + m + 1, cmp);
	ll l = 0, r = 1e18, ans = 0;
	while(l <= r){
		ll mid = (l + r) >> 1;
		if(check(mid))ans = mid, l = mid + 1;
		else r = mid - 1;
	}
	printf("%lld\n",ans);
	return 0;
}

B 绽放的花火

首先发现维度是假的,只要知道 \(\sum n_i\) 即可

\(f_i\) 表示从 \(i\) 到第 \(i +1\) 号点的期望步数

每次有 \(p\) 的概率到 \(i +1\)\(1 - p\) 的概率到 \(i - 1\) , 到 \(i - 1\) 还需要 \(f_{i -1} + f_i\) 才能到 \(i +1\)

那么 $f_i = 1 + (1 - p) (f_i + f_{i - 1}) $

移项即可得到递推公式, 然后到 \(\sum n_i\) 的期望步数就是 \(\sum f_i\)

code
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<queue>
#include<vector>
#include<set>
#include<map>
#include<iostream>
#include<random>

using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;

const int maxn = 500005;
const int mod = 1e9 + 7;
inline int read(){
	int x = 0; char c = getchar();
	while(c < '0' || c > '9')c = getchar();
	do{x = (x << 3) + (x << 1) + (c ^ 48); c = getchar();}while(c <= '9' && c >= '0');
	return x;
}
int n, sum, p;
int f[maxn];
ll qpow(int x, int y){
	ll ans = 1;
	for(; y; y >>= 1, x = 1ll * x * x % mod)if(y & 1)ans = 1ll * ans * x % mod;
	return ans;
}
int main(){
	int t = read();
	for(int ask = 1; ask <= t; ++ask){
		n = read(); sum = 0;
		for(int i = 1; i <= n; ++i)sum += read();
		sum = sum - n  + 1;
		p = read();
		int invp = qpow(p, mod - 2);
		f[1] = 1;
		for(int i = 2; i < sum; ++i)f[i] = 1ll * invp * ((1ll * (1 - p + mod) * f[i - 1] % mod + 1) % mod) % mod;
		int ans = 0;
		for(int i = 1; i < sum; ++i)ans = (ans + f[i]) % mod;
		for(int i = 1; i < sum; ++i)printf("%d ",f[i]);
		printf("%d\n",ans);
	}	
	return 0;
}

C 美化数列

线段树维护等差数列,等比数列,对应加斐波那契数列

等差好处理, 维护首项 \(k\), 以及公差 \(d\), 因为是加法, 所以首项和公差都有可加性

等比数列, 发现公比 \(D\) 是固定的,那么首项就可以直接相加,预处理 \(D^n\) 可以快速求首项, 区间和预处理 \(\sum_{i= 1}^n D^i\)即可

对应加斐波那契, 发现对应区间加一段斐波那契,可以转化为对应区间加上 \(f1\) 倍的从 \(fib_1\) 开始的序列, \(f2\) 倍从 \(fib_2\) 开始的序列, 预处理 \(fib\) 每一项是多少 \(fib_1\)\(fib_2\) 构成的即可快速 \(push\_down\)

码量感人

code
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<queue>
#include<vector>
#include<set>
#include<map>
#include<iostream>
#include<random>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;
const int maxn = 100005;
const int mod = 19260817;
const int inv2 = 9630409;
inline int read(){
	int x = 0; char c = getchar();
	while(c < '0' || c > '9')c = getchar();
	do{x = (x << 3) + (x << 1) + (c ^ 48); c = getchar();}while(c <= '9' && c >= '0');
	return x;
}
int fib[maxn], a[maxn], dpow[maxn], sd[maxn], f1[maxn], f2[maxn], sb[maxn], sf1[maxn], sf2[maxn];
int n, m, D;
struct tree{
	struct node{
		int sum, k1, d, k2, f1, f2; 
	}t[maxn << 2 | 1];
	void push_up(int x){t[x].sum = (t[x << 1].sum + t[x << 1 | 1].sum) % mod;}
	void push_down(int x, int l, int r){
		int mid = (l + r) >> 1, ls = x << 1, rs = x << 1 | 1;
		if(t[x].d || t[x].k1){
			t[ls].d = (t[ls].d + t[x].d) % mod;
			t[rs].d = (t[rs].d + t[x].d) % mod;
			int nk = (t[x].k1 + 1ll * (mid + 1 - l) * t[x].d % mod) % mod;
			t[ls].k1 = (t[ls].k1 + t[x].k1) % mod;
			t[rs].k1 = (t[rs].k1 + nk) % mod;
			t[ls].sum = (t[ls].sum + 1ll * (t[x].k1 + 1ll * (mid - l) * t[x].d % mod + t[x].k1) % mod * (mid - l + 1) % mod * inv2 % mod) % mod;
			t[rs].sum = (t[rs].sum + 1ll * (nk + 1ll * (r - mid - 1) * t[x].d % mod + nk) % mod * (r - mid) % mod * inv2 % mod) % mod;
			t[x].k1 = t[x].d = 0;
		}
		if(t[x].k2){
			t[ls].k2 = (t[x].k2 + t[ls].k2) % mod;
			int nk = 1ll * t[x].k2 * dpow[mid + 1 - l] % mod;
			t[rs].k2 = (nk + t[rs].k2) % mod;
			t[ls].sum = (t[ls].sum + 1ll * t[x].k2 * sd[mid - l] % mod) % mod;
			t[rs].sum = (t[rs].sum + 1ll * nk * sd[r - mid - 1] % mod) % mod;
			t[x].k2 = 0;
		}
		if(t[x].f1 || t[x].f2){
			t[ls].f1 = (t[ls].f1 + t[x].f1) % mod;
			t[ls].f2 = (t[ls].f2 + t[x].f2) % mod;
			int len = mid - l + 1 ;
			t[ls].sum = (t[ls].sum + 1ll * t[x].f1 * sb[len] % mod + 1ll * t[x].f2 * (sb[len + 1] - 1) % mod) % mod;
			int nf1 = 1ll * t[x].f1 * f1[len + 1] % mod + 1ll * t[x].f2 * f1[len + 2] % mod;
			int nf2 = 1ll * t[x].f1 * f2[len + 1] % mod + 1ll * t[x].f2 * f2[len + 2] % mod;
			t[rs].f1 = (t[rs].f1 + nf1) % mod;
			t[rs].f2 = (t[rs].f2 + nf2) % mod;
			t[rs].sum = (t[rs].sum + 1ll * nf1 * sb[r - mid] % mod + 1ll * nf2 * (sb[r - mid + 1] - 1) % mod) % mod;
			t[x].f1 = t[x].f2 = 0; 
		}
	}
	void built(int x, int l, int r){
		if(l == r){
			t[x].sum = a[l];
			return;
		}
		int mid = (l + r) >> 1;
		built(x << 1, l, mid);
		built(x << 1 | 1, mid + 1, r);
		push_up(x);
	}
	void modify_dc(int x, int l, int r, int L, int R, int k, int d){
		if(L <= l && r <= R){
			t[x].k1 = (t[x].k1 + k) % mod;
			t[x].d = (t[x].d + d) % mod;
			t[x].sum = (t[x].sum + 1ll * (k + 1ll * (r - l) * d % mod + k) % mod * (r - l + 1) % mod * inv2 % mod) % mod;
			return;
		}
		push_down(x, l, r);
		int mid = (l + r) >> 1;
		if(L <= mid) {
			modify_dc(x << 1, l, mid, L, R, k, d);
			k = (k + 1ll * (mid - max(L, l) + 1) * d % mod) % mod;
		}
		if(R > mid) modify_dc(x << 1 | 1, mid + 1, r, L, R, k, d);
		push_up(x);
	}
	void modify_db(int x, int l, int r, int L, int R, int k){
		if(L <= l && r <= R){
			t[x].k2 = (t[x].k2 + k) % mod;
			t[x].sum = (t[x].sum + 1ll * sd[r - l] * k) % mod;
			return;
		}
		push_down(x, l, r);
		int mid = (l + r) >> 1;
		if(L <= mid){
			modify_db(x << 1, l, mid, L, R, k);
			k = 1ll * k * dpow[mid - max(l, L) + 1] % mod;
		}
		if(R > mid)modify_db(x << 1 | 1, mid + 1, r, L, R, k);
		push_up(x);
	}
	void modify_fib(int x, int l, int r, int L, int R, int nf1, int nf2){
		if(L <= l && r <= R){
			t[x].sum = (0ll + t[x].sum + 1ll * nf1 * sb[r - l + 1] % mod + 1ll * nf2 * (sb[r - l + 2] - 1) % mod) % mod;
			t[x].f1 = (t[x].f1 + nf1) % mod;
			t[x].f2 = (t[x].f2 + nf2) % mod;
			return;
		}
		push_down(x, l, r);
		int mid = (l + r) >> 1;
		if(L <= mid){
			modify_fib(x << 1, l, mid, L, R, nf1, nf2);
			int len = mid + 2 - max(l, L), lf1 = nf1, lf2 = nf2;
			nf1 = 1ll * lf1 * f1[len] % mod + 1ll * lf2 * f1[len + 1] % mod;
			nf2 = 1ll * lf1 * f2[len] % mod + 1ll * lf2 * f2[len + 1] % mod;
		}
		if(R > mid)modify_fib(x << 1 | 1, mid + 1, r, L, R, nf1, nf2);
		push_up(x);
	}
	int query(int x, int l, int r, int L, int R){
		if(L <= l && r <= R)return t[x].sum;
		push_down(x, l, r);
		int mid = (l + r) >> 1, ans = 0;
		if(L <= mid)ans += query(x << 1, l, mid, L, R);
		if(R > mid)ans = (ans + query(x << 1 | 1, mid + 1, r, L, R)) % mod;
		return ans % mod;
	}
}t;
int main(){
	n = read(), m = read(), D = read();
	for(int i = 1; i <= n; ++i)a[i] = read();
	t.built(1, 1, n);
	for(int i = 1; i <= n; ++i)a[i] = 0;
	dpow[0] = 1; for(int i = 1; i <= n; ++i)dpow[i] = 1ll * dpow[i - 1] * D % mod;
	sd[0] = 1; for(int i = 1; i <= n; ++i)sd[i] = (sd[i - 1] + dpow[i]) % mod;
	fib[1] = fib[2] = 1; f1[1] = f2[2] = 1;
	for(int i = 3; i <= n; ++i)fib[i] = (fib[i - 1] + fib[i - 2]) % mod;
	for(int i = 3; i <= n; ++i)f1[i] = (f1[i - 1] + f1[i - 2]) % mod;
	for(int i = 3; i <= n; ++i)f2[i] = (f2[i - 1] + f2[i - 2]) % mod;
	for(int i = 1; i <= n; ++i)sb[i] = (sb[i - 1] + fib[i]) % mod;
	for(int i = 1; i <= m; ++i){
		int o = read(), l = read(), r = read();
		if(o == 1){
			int k = read(), d = read();
			t.modify_dc(1, 1, n, l, r, k, d);
		}
		if(o == 2){
			int k = read();
			t.modify_db(1, 1, n, l, r, k);
		}
		if(o == 3) t.modify_fib(1, 1, n, l, r, 1, 0);
		if(o == 4) printf("%d\n",t.query(1, 1, n, l, r));
	}	
	return 0;
}

D ZB的旋转树

image

posted @ 2022-08-20 16:38  Chen_jr  阅读(59)  评论(0编辑  收藏  举报