ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

八一特别行动

2022-08-03 08:35:46  阅读:114  来源: 互联网

标签:特别 八一 return int mid len maxn 行动 include


题目背景:(为啥放图片你可以猜猜)

image

image

A. 南

设\(g_i\)表示有\(i\)种武器,要拿到\(n\)种的期望花费

根据拿到与已有武器种类是否相同的概率,显然有

\(g_i = \frac{i}{n}g_i + \frac{n - i}{n}g_{i + 1} + cost\)

\(cost\)为该次购买对总期望的贡献,每次购买会令后面所有购买花费\(+1\),那么实际上\(cost\)就是期望次数

与之前相同,显然有

\(f_i = \frac{i}{n}f_i + \frac{n - i}{n}f_{i + 1} + 1\)

code
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long ll;
const int maxn = 10005;
double f[maxn], g[maxn];
int main(){
	int x; scanf("%d",&x);
	double n = x;
	for(int i = x - 1; i >= 0; --i){
		f[i] = f[i + 1] + n / (n - i);
		g[i] = g[i + 1] + n / (n - i) * f[i];
	}
	printf("%.2lf\n",g[0]);
	return 0;
}

B. 昌

考场贪心假了

设\(f_i\)表示\(i\)是子树内第\(f_i\)大的数

对取\(min\)是对子节点求和

取\(max\)是取子节点最小值

code
#include<cstdio>
#include<queue>
using namespace std;
typedef long long ll;
const int maxn = 300005;
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;
}
queue<int>q;
int n,op[maxn],fa[maxn], f[maxn], rd[maxn];
int main(){
	n = read();
	for(int i = 1; i <= n; ++i)op[i] = read();
	for(int i = 2; i <= n; ++i)++rd[fa[i] = read()];
	int k = 0;
	for(int i = 1; i <= n; ++i)if(!rd[i])++k;
	for(int i = 1; i <= n; ++i)if(!rd[i])q.push(i),f[i] = 1;
	while(!q.empty()){
		int x = q.front(); q.pop();
		if(fa[x]){
			--rd[fa[x]];
			if(rd[fa[x]] == 0)q.push(fa[x]);
			if(op[fa[x]]){
				if(!f[fa[x]])f[fa[x]] = f[x];
				else f[fa[x]] = min(f[fa[x]], f[x]);
			}else f[fa[x]] += f[x];
		}
	}
	printf("%d\n",k - f[1] + 1);
	return 0;
}

C. 起

预处理中心扩展出的最大矩形

查询二分答案,对比边界小答案的子矩形求最值,如果大于等于当前答案,那么存在

这样实际上保证了一定至少有\(mid\)的扩展在询问内

rt
image

code
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<cmath>

using namespace std;

typedef long long ll;
const int maxn = 505;
int n, m, q;
char c[maxn];
int b[maxn][maxn], w[maxn][maxn], p[maxn][maxn], g[maxn][maxn];
int col[maxn][maxn], ml[maxn][maxn];
bool check(int x, int y,int len){
	int size = len * len;
	if(b[x][y] - b[x][y - len] - b[x - len][y] + b[x - len][y - len] != size)return false;
	if(w[x][y + len] - w[x][y] - w[x - len][y + len] + w[x - len][y] != size)return false;
	if(p[x + len][y] - p[x][y] - p[x + len][y - len] + p[x][y - len] != size)return false;
	if(g[x + len][y + len] - g[x][y + len] - g[x + len][y] + g[x][y] != size)return false;
	return true;
}
void mr(int i,int j){
	int l = 2, r = min(min(i, j),min(n - i , m - j)), ans = 1;
	while(l <= r){
		int mid = (l + r) >> 1;
		if(check(i, j, mid))ans = mid, l = mid + 1;
		else r = mid - 1;
	}
	ml[i][j] = ans;
}
struct ST{
	int st[maxn][maxn][21][21];
	void prework(){
		for(int i = 1; i <= n; ++i)
			for(int j = 1; j <= m; ++j)
				st[i][j][0][0] = ml[i][j];
		for(int k = 0; (1 << k) <= n; ++k)
			for(int l = 0; (1 << l) <= m; ++l)
				if(k || l){
					if(l){
						for(int i = 1; i + (1 << k) - 1 <= n; ++i)
							for(int j = 1; j + (1 << l) - 1 <= m; ++j)
								st[i][j][k][l] = max(st[i][j][k][l - 1], st[i][j + (1 << (l - 1))][k][l - 1]);
					}
					else{
						for(int i = 1; i + (1 << k) - 1 <= n; ++i)
							for(int j = 1; j + (1 << l) - 1 <= m; ++j)
								st[i][j][k][l] = max(st[i][j][k - 1][l], st[i + (1 << (k - 1))][j][k - 1][l]);
					}
				}
	}
	int query(int a, int b, int c, int d){
		if(c < a || d < b)return 0;
		int k = log2(c - a + 1), l = log2(d - b + 1);
		return max(max(st[a][b][k][l], st[c - (1 << k) + 1][b][k][l]), max(st[a][d - (1 << l) + 1][k][l], st[c - (1 << k) + 1][d - (1 << l) + 1][k][l]));
	}
}s;
bool check(int a, int b, int c, int d, int len){
	return s.query(a + len - 1, b + len - 1, c - len, d - len) >= len ? 1 : 0;
}
int mrr(int a, int b, int c, int d){
	int l = 1, r = min(c - a + 1,d - b + 1) / 2, ans = 0;
	while(l <= r){
		int mid = (l + r) >> 1;
		if(check(a, b, c, d, mid))ans = mid, l = mid + 1;
		else r = mid - 1;
	}
	return ans * ans * 4;
}
int main(){
	scanf("%d%d%d", &n, &m, &q);
	for(int i = 1; i <= n; ++i){
		scanf("%s",c + 1);
		for(int j = 1; j <= m; ++j){
			if(c[j] == 'B')col[i][j] = 1;
			if(c[j] == 'W')col[i][j] = 2;
			if(c[j] == 'P')col[i][j] = 3;
			if(c[j] == 'G')col[i][j] = 4;
		}
	}
	for(int i = 1; i <= n; ++i)
		for(int j = 1; j <= m; ++j)
			if(col[i][j] == 1)b[i][j] = 1;
			else if(col[i][j] == 2)w[i][j] = 1;
			else if(col[i][j] == 3)p[i][j] = 1;
			else g[i][j] = 1;
	for(int i = 1; i <= n; ++i)
		for(int j = 1; j <= m; ++j)
		 	b[i][j] = b[i][j] + b[i - 1][j] + b[i][j - 1] - b[i - 1][j - 1];
	for(int i = 1; i <= n; ++i)
		for(int j = 1; j <= m; ++j)
		 	w[i][j] = w[i][j] + w[i - 1][j] + w[i][j - 1] - w[i - 1][j - 1];
	for(int i = 1; i <= n; ++i)
		for(int j = 1; j <= m; ++j)
		 	p[i][j] = p[i][j] + p[i - 1][j] + p[i][j - 1] - p[i - 1][j - 1];
	for(int i = 1; i <= n; ++i)
		for(int j = 1; j <= m; ++j)
		 	g[i][j] = g[i][j] + g[i - 1][j] + g[i][j - 1] - g[i - 1][j - 1];
	for(int i = 1; i < n; ++i)
		for(int j = 1; j < m; ++j)
			if(col[i][j] == 1 && col[i][j + 1] == 2 && col[i + 1][j] == 3 && col[i + 1][j + 1] == 4)
				mr(i, j);
	s.prework();
	for(int i = 1; i <= q; ++i){
		int a, b, c, d;
		scanf("%d%d%d%d", &a, &b, &c, &d);
		printf("%d\n",mrr(a, b, c, d));
	}
	return 0;
}

根号分治,小于根号的直接背包,用\(DZYlovesmath\)那种优化

大于根号的另设一种\(dp\)

显然选取不会超过\(\sqrt n\)个

\(g[i][j]\) 表示选取了\(i\)个,容量为\(j\)的方案数

考虑都由大小为\(\sqrt n + 1\)的物品变化而成

两种操作

  1. 对每个物品大小 + 1

2 加入新物品

code
#include<bits/stdc++.h>
using namespace std;
const int maxn = 100005;
const int mod = 23333333;
int f[maxn],n,g[333][maxn];
int main(){
	scanf("%d", &n);
	int m = sqrt(n);
	f[0] = 1;
	for(int i = 1; i <= m; ++i){
		for(int j = i; j <= n; ++j)
		  f[j] = (f[j] + f[j - i]) % mod;
		long long up = 1ll * i * (i + 1);
		for(int j = n; j >= up; --j) f[j] = (f[j] - f[j - up] + mod) % mod;
	}
	g[0][0] = 1;
	for(int i = 0; i <= m; ++i){
		for(int j = 0; j <= n; ++j){
			if(j + i <= n && i)g[i][i + j] = (g[i][i + j] + g[i][j]) % mod;
			if(j + m + 1 <= n)g[i + 1][j + m + 1] = (g[i + 1][j + m + 1] + g[i][j]) % mod;
		}
	}
	++g[1][0];
	int ans = 0;
	for(int i = 0; i <= n; ++i){
		for(int j = 1; j <= m; ++j){
			ans = (ans + 1ll * f[i] * g[j][n - i] % mod) % mod;
		}
	}
	printf("%d\n",ans);
	return 0;
}

标签:特别,八一,return,int,mid,len,maxn,行动,include
来源: https://www.cnblogs.com/Chencgy/p/16543360.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有