Live2D

2021-06-19 集训题解

T1 区间第 k 小

题目传送门

Description

给出一个长度为 \(n\) 的序列,给出 \(w\),有 \(q\) 次查询,每次查询给出 \(l,r,k\),求出忽视掉区间出现次数 \(\ge w\) 的数之后第 \(k\) 大是多少,如没有 \(k\) 个则输出 \(n\)

\(n\le 10^5,0\le a_i<n\)

Solution

考虑分块。我们可以先提前处理出 \(s1_{i,j,k}\)\(s2_{i,j}\)\(s1_{i,j,k}\) 表示区间上第 \(i\) 个块到第 \(j\) 个块第 \(k\) 个值域块出现次数 \(\le w\) 的数的出现次数之和,\(s2_{i,j}\) 表示前面 \(i\) 个块 \(j\) 的出现次数。

然后查询的时候就可以算出每个值域块的个数,以及每个数的出现次数,用平衡树上查询第 \(k\) 大的方法查就好了。

时空复杂度均为 \(\Theta(n\sqrt n)\)

Code

#include <bits/stdc++.h>
using namespace std;

#define Int register int
#define MAXN 100005
#define MAXM 355

template <typename T> void read (T &x){char c = getchar ();x = 0;int f = 1;while (c < '0' || c > '9') f = (c == '-' ? -1 : 1),c = getchar ();while (c >= '0' && c <= '9') x = x * 10 + c - '0',c = getchar ();x *= f;}
template <typename T,typename ... Args> void read (T &x,Args& ... args){read (x),read (args...);}
template <typename T> void write (T x){if (x < 0) x = -x,putchar ('-');if (x > 9) write (x / 10);putchar (x % 10 + '0');}
template <typename T> void chkmax (T &a,T b){a = max (a,b);}
template <typename T> void chkmin (T &a,T b){a = min (a,b);}

int n,w,T,siz,cnt,type,a[MAXN],t[MAXN],t1[MAXM],bel[MAXN],col[MAXN],cor[MAXN],s1[MAXM][MAXM][MAXM],s2[MAXM][MAXN]; 

void buildit (){
	siz = sqrt (n),cnt = (n - 1) / siz + 1;
	for (Int i = 1;i <= n;++ i) bel[i] = (i - 1) / siz + 1,cor[bel[i]] = i,col[bel[i]] = !col[bel[i]] ? i : col[bel[i]];
	for (Int j = 1;j <= cnt;++ j)
		for (Int i = 1;i <= cor[j];++ i)
			s2[j][a[i]] ++;
	for (Int i = 1;i <= cnt;++ i){
		for (Int j = i;j <= cnt;++ j){
			for (Int k = 1;k <= cnt;++ k) s1[i][j][k] = s1[i][j - 1][k];
			for (Int k = col[j];k <= cor[j];++ k){
				++ t[a[k]];
				if (t[a[k]] < w) s1[i][j][bel[a[k]]] ++;
				else if (t[a[k]] == w) s1[i][j][bel[a[k]]] -= w - 1;
			}
		}
		for (Int j = 1;j <= n;++ j) t[j] = 0;
	}
}

int query (int l,int r,int k){
	int res = n + 1;
	if (bel[l] == bel[r]){
		for (Int i = 1;i <= cnt;++ i) t1[i] = 0;
		for (Int i = l;i <= r;++ i){
			t[a[i]] ++;
			if (t[a[i]] < w) t1[bel[a[i]]] ++;
			else if (t[a[i]] == w) t1[bel[a[i]]] -= w - 1;
		}
		for (Int i = 1;i <= cnt;++ i)
			if (t1[i] >= k){
				for (Int j = col[i];j <= cor[i];++ j)
					if (t[j] >= w) continue;
					else if (t[j] >= k){
						res = j;
						break;
					}
					else k -= t[j];
				break;
			}
			else k -= t1[i];
		for (Int i = l;i <= r;++ i) t[a[i]] --;
		return res - 1;
	}
	int qL = bel[l],qR = bel[r];
	for (Int i = 1;i <= cnt;++ i) t1[i] = s1[qL + 1][qR - 1][i];
	for (Int i = l,h;i <= cor[qL];++ i){
		t[a[i]] ++;
		if ((h = t[a[i]] + s2[qR - 1][a[i]] - s2[qL][a[i]]) < w) t1[bel[a[i]]] ++;
		else if (h == w) t1[bel[a[i]]] -= w - 1;
	}
	for (Int i = col[qR],h;i <= r;++ i){
		t[a[i]] ++;
		if ((h = t[a[i]] + s2[qR - 1][a[i]] - s2[qL][a[i]]) < w) t1[bel[a[i]]] ++;
		else if (h == w) t1[bel[a[i]]] -= w - 1;
	}
	for (Int i = 1;i <= cnt;++ i)
		if (t1[i] >= k){
			for (Int j = col[i];j <= cor[i];++ j){
				int h = t[j] + s2[qR - 1][j] - s2[qL][j];
				if (h >= w) continue;
				else if (h >= k){res = j;break;}
				else k -= h;
			}
			break;
		}
		else k -= t1[i];
	for (Int i = l;i <= cor[qL];++ i) t[a[i]] --;
	for (Int i = col[qR];i <= r;++ i) t[a[i]] --;
	return res - 1;
}

signed main(){
	read (n,w,T,type),++ w;
	for (Int i = 1;i <= n;++ i) read (a[i]),++ a[i];
	buildit ();int lst = 0;
	while (T --> 0){
		int l,r,k;read (l,r,k);
		l ^= lst * type,r ^= lst * type,k ^= lst * type;
		write (lst = query (l,r,k)),putchar ('\n');
	}
	return 0;
}

T2 求和

题目传送门

Description

Solution

发现式子可以化成:

\[\sum_{x=1}^{n} \sum_{d=1}^{k} f_d(x)(2\sum_{i=1}^{\lfloor\frac{n}{x}\rfloor} \varphi(i)-1) \]

前面那个可以 \(\text{Powerful Number}\) 做,后面的那个可以杜教筛。拟合函数用 \(\mu\) 就可以了。

复杂度显然是 \(\Theta(n^{2/3})\)

Code

#include <bits/stdc++.h>
using namespace std;

#define Int register long long
#define mod 1073741824
#define int long long
#define MAXN 5000005

template <typename T> void read (T &x){char c = getchar ();x = 0;int f = 1;while (c < '0' || c > '9') f = (c == '-' ? -1 : 1),c = getchar ();while (c >= '0' && c <= '9') x = x * 10 + c - '0',c = getchar ();x *= f;}
template <typename T,typename ... Args> void read (T &x,Args& ... args){read (x),read (args...);}
template <typename T> void write (T x){if (x < 0) x = -x,putchar ('-');if (x > 9) write (x / 10);putchar (x % 10 + '0');}
template <typename T> void chkmax (T &a,T b){a = max (a,b);}
template <typename T> void chkmin (T &a,T b){a = min (a,b);}

int mul (int a,int b){return 1ll * a * b % mod;}
int dec (int a,int b){return a >= b ? a - b : a + mod - b;}
int add (int a,int b){return a + b >= mod ? a + b - mod : a + b;}
int qkpow (int a,int b){
	int res = 1;for (;b;b >>= 1,a = mul (a,a)) if (b & 1) res = mul (res,a);
	return res;
}
void Add (int &a,int b){a = add (a,b);}
int upd (int x){return x < 0 ? x + mod : x;}

#define lim 5e6

int N,K;
bool vis[MAXN];
int sq,cnt,ptot,pf[MAXN],mu[MAXN],mn[MAXN],mx[MAXN],dF[MAXN],id1[MAXN],id2[MAXN],phi[MAXN],dmu[MAXN],num[MAXN],dphi[MAXN],prem[MAXN],prep[MAXN],preF[MAXN],idsum[MAXN],prime[MAXN];

int getF (int n){
	if (n == 1) return K;
	if (mx[n] > K) return 0;
	return mul (upd (idsum[n] & 1 ? -1 : 1),K - mx[n] + 1);
}

int getSum (int n){
	if (n & 1) return mul ((n + 1) / 2 % mod,n % mod);
	else return mul (n / 2 % mod,(n + 1) % mod);
}

void Euler (int up){
	mu[1] = phi[1] = 1;
	for (Int i = 2;i <= up;++ i){
		if (!vis[i]) prime[++ ptot] = i,mx[i] = mn[i] = idsum[i] = 1,mu[i] = -1,phi[i] = i - 1;
		for (Int j = 1;j <= ptot && i * prime[j] <= up;++ j){
			vis[i * prime[j]] = 1,idsum[i * prime[j]] = idsum[i] + 1;
			if (i % prime[j]) 
				mx[i * prime[j]] = max (mx[i],1ll),mn[i * prime[j]] = 1,
				mu[i * prime[j]] = -mu[i],phi[i * prime[j]] = phi[i] * (prime[j] - 1);
			else{
				mx[i * prime[j]] = max (mx[i],mn[i] + 1),mn[i * prime[j]] = mn[i] + 1;
				phi[i * prime[j]] = phi[i] * prime[j];
				break;
			}
		}
	}
	for (Int i = 1;i <= up;++ i) prem[i] = add (prem[i - 1],upd (mu[i])),prep[i] = add (prep[i - 1],phi[i]),preF[i] = add (preF[i - 1],getF (i));
} 

int getmu (int n){
	if (n <= lim) return prem[n];
	int pos = n <= sq ? id1[n] : id2[N / n];
	if (~dmu[pos]) return dmu[pos];
	int &res = dmu[pos] = 1;
	for (Int l = 2,r;l <= n;l = r + 1) r = n / (n / l),res = dec (res,mul (r - l + 1,getmu (n / l)));
	return res;
}

int getphi (int n){
	if (n <= lim) return prep[n];
	int pos = n <= sq ? id1[n] : id2[N / n];
	if (~dphi[pos]) return dphi[pos];
	int &res = dphi[pos] = 1ll * n * (n + 1) / 2 % mod;
	for (Int l = 2,r;l <= n;l = r + 1) r = n / (n / l),res = dec (res,mul (r - l + 1,getphi (n / l)));
	return res;
}

#define inf 1e9
#define pii pair<int,int>

int tot;
pii pwer[1000005];

void dfs (int now,int n,int down,int up){
	pwer[++ tot].first = n;
	if (up == inf) pwer[tot].second = max (K - down,0ll) + min (down,K) / 2;
	else pwer[tot].second = min (up,K) / 2;
	for (Int i = now + 1;i <= ptot && n <= N / prime[i] / prime[i];++ i)
		for (Int pw = prime[i] * prime[i],e = 2;n * pw <= N;pw *= prime[i],e ++){
			if (e & 1) dfs (i,n * pw,down,min (up,e));
			else dfs (i,n * pw,max (down,e),up);
		}
}

int getf (int n){
	if (n <= lim) return preF[n];
	int pos = n <= sq ? id1[n] : id2[N / n];
	if (~dF[pos]) return dF[pos];
	int &res = dF[pos] = 0;
	for (Int l = 1,r;l <= tot && num[l] <= n;l = r + 1)
		r = n / (n / num[l]),
		r = upper_bound (num + 1,num + tot + 1,r) - num - 1,
		Add (res,mul (dec (pf[r],pf[l - 1]),getmu (n / num[l])));
	return res;
}

signed main(){
	read (N,K),sq = sqrt (N),Euler (min (N,(int)lim));
	for (Int l = 1,r;l <= N;l = r + 1){
		r = N / (N / l);
		if (N / l <= sq) id1[N / l] = ++ cnt;
		else id2[N / (N / l)] = ++ cnt;
	}
	for (Int i = 1;i <= cnt;++ i) dF[i] = dmu[i] = dphi[i] = -1;
	dfs (0,1,0,inf),sort (pwer + 1,pwer + tot + 1);
	for (Int i = 1;i <= tot;++ i) num[i] = pwer[i].first,pf[i] = add (pf[i - 1],pwer[i].second);
	int ans = 0;
	for (Int l = 1,r,lst = 0;l <= N;l = r + 1){
		r = N / (N / l);int t = getphi (N / l),h = getf (r);
		Add (ans,mul (dec (h,lst),dec (add (t,t),1))),lst = h;
	}
	write (ans),putchar ('\n');
	return 0;
}

T3

题目传送门

Description

Solution

Code

#include <bits/stdc++.h>
using namespace std;

#define Int register int
#define MAXN 1000005

template <typename T> void read (T &x){char c = getchar ();x = 0;int f = 1;while (c < '0' || c > '9') f = (c == '-' ? -1 : 1),c = getchar ();while (c >= '0' && c <= '9') x = x * 10 + c - '0',c = getchar ();x *= f;}
template <typename T,typename ... Args> void read (T &x,Args& ... args){read (x),read (args...);}
template <typename T> void write (T x){if (x < 0) x = -x,putchar ('-');if (x > 9) write (x / 10);putchar (x % 10 + '0');}
template <typename T> void chkmax (T &a,T b){a = max (a,b);}
template <typename T> void chkmin (T &a,T b){a = min (a,b);}

vector <int> G[MAXN];
int n,len1,len2,f[MAXN],s[MAXN],t[MAXN];

void dfs (int u,int fa){
	for (Int v : G[u]) if (v ^ fa) dfs (v,u),f[u] -= f[v];
	int now = f[u] * (u > fa ? 1 : -1);
	for (Int v : G[u]) if (v ^ fa) now += f[v] * (u > v ? 1 : -1);
	if (now > 0) for (Int i = 1;i <= now;++ i) t[++ len1] = u;
	else for (Int i = 1;i <= -now;++ i) s[++ len2] = u;
}

signed main(){
	read (n);
	for (Int i = 1;i <= n;++ i) read (f[i]);
	for (Int i = 2,u,v;i <= n;++ i) read (u,v),G[u].push_back (v),G[v].push_back (u);
	dfs (1,0),sort (s + 1,s + len2 + 1),sort (t + 1,t + len1 + 1);
	write (len1),putchar ('\n');
	for (Int i = 1;i <= len1;++ i) write (s[i]),putchar (' '),write (t[i]),putchar ('\n');
	return 0;
}
posted @ 2021-06-20 11:03  Dark_Romance  阅读(46)  评论(0编辑  收藏  举报