zoukankan      html  css  js  c++  java
  • 1024考试总结

    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("
    ");
    	}
    	
    	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;
    }
    
  • 相关阅读:
    二十八 .Django中模型类中Meta元对象了解
    【POJ2376】Cleaning Shifts
    【CF600E】Lomsat gelral
    【hiho1035】自驾旅行III
    【模板】manachar
    【hiho1065】全图传送
    【洛谷P1450】硬币购物
    【HDU2204】Eddy's爱好
    【CF208E】Blood Cousins
    【CF451E】Devu and Flowers
  • 原文地址:https://www.cnblogs.com/czhui666/p/13871880.html
Copyright © 2011-2022 走看看