ICode9

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

1024考试总结

2020-10-25 07:31:40  阅读:210  来源: 互联网

标签:总结 1024 ch 咖啡 int long isdigit 考试 getchar


1024考试总结

T1

​ 题目大意:

​ 理想的光滑平面上有\(n\)个加速阶段,每个加速阶段的加速度和持续时间分别是\(a[i], t[i]\),现在让你求一种\(n\)个阶段的排列顺序,使得新的顺序的位移比输入的顺序的位移相差最大,输出最大差值.\(n <= 1e5\).

​ 贪心,按\(a[i]\)从大到小排序会得到最优顺序.

​ 证明用临项交换:假设我们要让先\(i\)后\(j\)比先\(j\)后\(i\)更优,那么:

​ \(vt_i + \frac{1}{2}a_it_i^2 + (v + a_it_i)t_j + \frac{1}{2} a_jt_j^2 > vt_j + \frac{1}{2}a_jt_j^2 + (v + a_jt_j)t_i + \frac{1}{2} a_it_i^2\)

​ 化简一下就可得到:\(a_i > a_j\).

#include <bits/stdc++.h>

using namespace std;

inline long long read() {
	long long s = 0, f = 1; char ch;
	while(!isdigit(ch = getchar())) (ch == '-') && (f = -f);
	for(s = ch ^ 48;isdigit(ch = getchar()); s = (s << 1) + (s << 3) + (ch ^ 48));
	return s * f;
}

const int N = 1e5 + 5;
int n;
struct node { int a, t; } x[N], y[N]; 

int cmp(node x, node y) { return x.a > y.a; }

long double calc() {
	long long vx = 0, vy = 0; long double res = 0;
	for(int i = 1;i <= n; i++) {
		res += (1ll * vy * y[i].t + 1ll * y[i].a * y[i].t * y[i].t / 2) - (1ll * vx * x[i].t + 1ll * x[i].a * x[i].t * x[i].t / 2);
		vx += 1ll * x[i].a * x[i].t; vy += 1ll * y[i].a * y[i].t;
	}
	return res;
}

int main() {
	
	n = read();
	for(int i = 1;i <= n; i++) y[i].a = x[i].a = read(), y[i].t = x[i].t = read();
	sort(y + 1, y + n + 1, cmp);
	printf("%.1Lf", calc());
	
	return 0;
}

T2

​ 题目大意:

​ 一个人买咖啡,他需要每个小时都喝一杯热咖啡,共有\(n\)小时,现在每个小时的咖啡价格不同,一杯咖啡可以持续热\(h\)个小时,可以同一个小时买多杯咖啡留给后面喝(只要没有凉就行),问怎么买咖啡可以使总钱数最小,输出从\(b\)到\(e\)小时内每个小时买了几杯咖啡.\(n <= 1e5\)

​ 假设我们现在在\(i\)小时,这个小时喝的咖啡肯定是在这个时间段买的:\([i - h + 1, i]\).所以我们要找到这个时间段的最小值的位置,在这个位置给\(i\)位置买一杯咖啡.这样可以花钱最少.所以维护一个单调队列就好了.

#include <bits/stdc++.h>

using namespace std;

inline long long read() {
	long long s = 0, f = 1; char ch;
	while(!isdigit(ch = getchar())) (ch == '-') && (f = -f);
	for(s = ch ^ 48;isdigit(ch = getchar()); s = (s << 1) + (s << 3) + (ch ^ 48));
	return s * f;
}

const int N = 1e5 + 5;
int n, h, b, e;
int a[N], q[N], ans[N];

int main() {
	
	while(cin >> n >> h >> b >> e) {
		for(int i = 1;i <= n; i++) a[i] = read(), ans[i] = 0;
		int l = 1, r = 0;
		for(int i = 1;i <= n; i++) {
			while(l <= r && q[l] <= i - h) l ++;
			while(l <= r && a[q[r]] >= a[i]) r --;
			q[++ r] = i;
			ans[q[l]] ++;
		}
		for(int i = b;i <= e; i++) printf("%d ", ans[i]);
		printf("\n");
	}
	
	return 0;
}

T3

题目链接

​ 题目大意:给你一维,二维,三维空间,再给\(n\)个点,让你求有多少个点对曼哈顿距离不超过\(d\).

​ 一维:直接双指针乱搞一下.

​ 二维:曼哈度距离转切比雪夫距离,\((x, y) -> (x + y, x - y)\),新坐标系里的切比雪夫距离就是原坐标系里的曼哈顿距离.首先按\(x\)从小到大排序,然后暴力枚举\(x\).\(y\)用数据结构维护一下.

​ 三维:还是曼哈顿距离转切比雪夫距离.新增了一维,但是每个点的坐标范围变成了\(1 <= x,y,z <= 75\).我们可以将z看做层数,计算每一层和层与层之间的答案.这样只用把\(x,y\)转化成切比雪夫距离就好了.然后我们每层搞一个二维前缀和.查询的时候可以\(O(1)\)查询.这里不同层的答案和相同层的答案分开处理比较好,因为相同层的答案会算重复.

#include <bits/stdc++.h>

#define ls(o) (o << 1)
#define rs(o) (o << 1 | 1)
#define mid ((l + r) >> 1)

using namespace std;

inline long long read() {
	long long s = 0, f = 1; char ch;
	while(!isdigit(ch = getchar())) (ch == '-') && (f = -f);
	for(s = ch ^ 48;isdigit(ch = getchar()); s = (s << 1) + (s << 3) + (ch ^ 48));
	return s * f;
}

const int N = 1e5 + 5;
int B, n, d, m;
int sum[80][150][150];
long long ans, ans1;
struct node { int x, y, z; } a[N];
struct tree { int sum; } t[N << 4];

int cmp(node a, node b) { return a.x < b.x; }

int dis(int i, int j) {
	if(B == 2) return abs(a[i].x - a[j].x) + abs(a[i].y - a[j].y);
	if(B == 3) return abs(a[i].x - a[j].x) + abs(a[i].y - a[j].y) + abs(a[i].z - a[j].z);
}

void work_B_1() {
	sort(a + 1, a + n + 1, cmp);
	int last = 1, tmp;
	for(int i = 1;i <= n; i++) {
		int j;
		for(j = last;j <= n; j++) 
			if(a[j].x - a[i].x > d) { last = j - 1; break; } 
		ans += j - i - 1;
	}
	printf("%lld", ans);	
}

void up(int o) {
	t[o].sum = t[ls(o)].sum + t[rs(o)].sum;
}

void insert(int o, int l, int r, int x, int f) {
	if(l == r) { t[o].sum += f; return ; } 
	if(x <= mid) insert(ls(o), l, mid, x, f);
	if(x > mid) insert(rs(o), mid + 1, r, x, f);
	up(o);
}

int query(int o, int l, int r, int x, int y) {
	if(x <= l && y >= r) { return t[o].sum; }
	int res = 0;
	if(x <= mid) res += query(ls(o), l, mid, x, y);
	if(y > mid) res += query(rs(o), mid + 1, r, x, y);
	return res;
}

void work_B_2() { 
	for(int i = 1;i <= n; i++) {
		int x = a[i].x, y = a[i].y;
		a[i].x = x + y; a[i].y = x - y;
	}
	sort(a + 1, a + n + 1, cmp);
	int last = 1; insert(1, -m, m, a[1].y, 1);
	for(int i = 2;i <= n; i++) {
		while(last < i && a[i].x - a[last].x > d) 
			insert(1, -m, m, a[last].y, -1), last ++;
		ans += query(1, -m, m, a[i].y - d, a[i].y + d);
		insert(1, -m, m, a[i].y, 1);
	}
	printf("%lld", ans);
}

void work_B_3() { 
	for(int i = 1;i <= n; i++) {
		int x = a[i].x, y = a[i].y;
		a[i].x = x + y; a[i].y = x - y + m; 
		sum[a[i].z][a[i].x][a[i].y] ++;
	}
	for(int i = 1;i <= m; i++)
		for(int j = 1;j <= 2 * m; j++)
			for(int k = 1;k <= 2 * m; k++) sum[i][j][k] += sum[i][j - 1][k] + sum[i][j][k - 1] - sum[i][j - 1][k - 1];
	for(int i = 1;i <= n; i++) {
		for(int j = max(1, a[i].z - d);j < a[i].z; j++) {
			int D = d - (a[i].z - j);
			int x1 = max(1, a[i].x - D), x2 = min(2 * m, a[i].x + D);
			int y1 = max(1, a[i].y - D), y2 = min(2 * m, a[i].y + D);
			ans += sum[j][x2][y2] - sum[j][x1 - 1][y2] - sum[j][x2][y1 - 1] + sum[j][x1 - 1][y1 - 1];
		}
		int D = d;
		int x1 = max(1, a[i].x - D), x2 = min(2 * m, a[i].x + D);
		int y1 = max(1, a[i].y - D), y2 = min(2 * m, a[i].y + D);
		ans1 += sum[a[i].z][x2][y2] - sum[a[i].z][x1 - 1][y2] - sum[a[i].z][x2][y1 - 1] + sum[a[i].z][x1 - 1][y1 - 1];
	}
	printf("%lld", ans + (ans1 - n) / 2);
}

int main() {
	
	B = read(); n = read(); d = read(); m = read();
	if(B == 1) for(int i = 1;i <= n; i++) a[i].x = read();
	if(B == 2) for(int i = 1;i <= n; i++) a[i].x = read(), a[i].y = read();
	if(B == 3) for(int i = 1;i <= n; i++) a[i].x = read(), a[i].y = read(), a[i].z = read();
	if(B == 1) { work_B_1(); }
	if(B == 2) { work_B_2(); }
	if(B == 3) { work_B_3(); }
	
	return 0;
}

标签:总结,1024,ch,咖啡,int,long,isdigit,考试,getchar
来源: https://www.cnblogs.com/czhui666/p/13871880.html

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

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

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

ICode9版权所有