Codeforces Round #731 (Div. 3) E. Air Conditioners(思维/DP/二分/区间最值/好题)

On a strip of land of length ??n there are ??k air conditioners: the ??i-th air conditioner is placed in cell ????ai (1≤????≤??1≤ai≤n). Two or more air conditioners cannot be placed in the same cell (i.e. all ????ai are distinct).

Each air conditioner is characterized by one parameter: temperature. The ??i-th air conditioner is set to the temperature ????ti.

Codeforces Round #731 (Div. 3) E. Air Conditioners(思维/DP/二分/区间最值/好题)Example of strip of length ??=6n=6, where ??=2k=2, ??=[2,5]a=[2,5] and ??=[14,16]t=[14,16].

For each cell ??i (1≤??≤??1≤i≤n) find it‘s temperature, that can be calculated by the formula

min1≤??≤??(????+|???????|),min1≤j≤k(tj+|aj?i|),

where |???????||aj?i| denotes absolute value of the difference ???????aj?i.

In other words, the temperature in cell ??i is equal to the minimum among the temperatures of air conditioners, increased by the distance from it to the cell ??i.

Let‘s look at an example. Consider that ??=6,??=2n=6,k=2, the first air conditioner is placed in cell ??1=2a1=2 and is set to the temperature ??1=14t1=14 and the second air conditioner is placed in cell ??2=5a2=5 and is set to the temperature ??2=16t2=16. In that case temperatures in cells are:

  1. temperature in cell 11 is: min(14+|2?1|,16+|5?1|)=min(14+1,16+4)=min(15,20)=15min(14+|2?1|,16+|5?1|)=min(14+1,16+4)=min(15,20)=15;
  2. temperature in cell 22 is: min(14+|2?2|,16+|5?2|)=min(14+0,16+3)=min(14,19)=14min(14+|2?2|,16+|5?2|)=min(14+0,16+3)=min(14,19)=14;
  3. temperature in cell 33 is: min(14+|2?3|,16+|5?3|)=min(14+1,16+2)=min(15,18)=15min(14+|2?3|,16+|5?3|)=min(14+1,16+2)=min(15,18)=15;
  4. temperature in cell 44 is: min(14+|2?4|,16+|5?4|)=min(14+2,16+1)=min(16,17)=16min(14+|2?4|,16+|5?4|)=min(14+2,16+1)=min(16,17)=16;
  5. temperature in cell 55 is: min(14+|2?5|,16+|5?5|)=min(14+3,16+0)=min(17,16)=16min(14+|2?5|,16+|5?5|)=min(14+3,16+0)=min(17,16)=16;
  6. temperature in cell 66 is: min(14+|2?6|,16+|5?6|)=min(14+4,16+1)=min(18,17)=17min(14+|2?6|,16+|5?6|)=min(14+4,16+1)=min(18,17)=17.

For each cell from 11 to ??n find the temperature in it.

大意就是有n个位置,其中有k个位置有空调,空调有两个参数ai和ti,ai表示其所在的位置,ti表示其本身温度,然后对于每个位置求出其最小的温度(\(min_{1<=j<=k}(t_j+|a_j - i|)\))。

这题大概有好多种做法,最简单的是执行一遍类似dp的过程,正着更新一遍再反着更新一遍取最小,正确性显然(但就是没想到):

#include <bits/stdc++.h>
using namespace std;
int n, k, ans[300005];
int a[300005], t[300005];
int main() {
	int q;
	cin >> q;
	for(int i = 1; i <= q; i++) {
		cin >> n >> k;
		for(int j = 1; j <= n; j++) {
			ans[j] = 0x3f3f3f3f;
		}
		for(int j = 1; j <= k; j++) {
			cin >> a[j];
		}
		for(int j = 1; j <= k; j++) {
			cin >> t[j];
			ans[a[j]] = t[j];
		}
		for(int i = 2; i <= n; i++) {
			ans[i] = min(ans[i], ans[i - 1] + 1);
		}
		for(int i = n - 1; i >= 1; i--) {
			ans[i] = min(ans[i], ans[i + 1] + 1);
		}
		for(int i = 1; i <= n; i++) {
			cout << ans[i] << " ";
		}
		cout << endl;
	}
	return 0;
}

由于我是脑瘫,只能想到没十年脑溢血想不到的做法:首先去绝对值,可以发现实际上是\(min(min_{1<=j<i}(t_j+i-a_j), min(_{i<=j<=k}(t_j+a_j-i))\)

因此先把输入的空调按a从小到大排序(后面二分会用到),然后预处理每个空调的t+a以及t-a存入数组,遍历每个位置,首先查找这个位置左右两边的空调的分界点在哪里,然后分别查询左右两边的区间最值,再分别+i、-以后求min即可。查询静态区间最值可以用RMQ算法。

#include <bits/stdc++.h>
using namespace std;
int n, k, ans[300005];
int a[300005], t[300005];
int f1[300005], f2[300005];
#define MAX 300005
int Min_dp1[MAX][100];
int Min_dp2[MAX][100];
struct node {
	int a, t;
} nd[300005];//仅用来给a排序 没啥用
bool cmp (node a, node b) {
	return a.a < b.a;
}
void RMQ1(int num)
{
    //建立动态表
    for(int i= 1; i <= num; i++) {
		Min_dp1[i][0] = f1[i];
	}
    for(int j=1;(1<<j)<=num;j++)
    {
        for(int i=1;i+(1<<j)-1<=num;i++)
        {
            int m = i+(1<<(j-1));
            Min_dp1[i][j] =min(Min_dp1[i][j-1],Min_dp1[m][j-1]);
        }   
    } 
}
int query1(int l,int r)
{
    int len = r-l+1;
    //C语言中log默认以e为底,所有除以log2 
    int m = (int)(log((double)len) / log(2.0));
    int minn = min(Min_dp1[l][m],Min_dp1[r-(1<<m)+1][m]);
    return minn;
}
void RMQ2(int num)
{
    //建立动态表
    for(int i= 1; i <= num; i++) {
		Min_dp2[i][0] = f2[i];
	}
    for(int j=1;(1<<j)<=num;j++)
    {
        for(int i=1;i+(1<<j)-1<=num;i++)
        {
            int m = i+(1<<(j-1));
            
            Min_dp2[i][j] =min(Min_dp2[i][j-1],Min_dp2[m][j-1]);
        }   
    } 
}
int query2(int l,int r)
{
    int len = r-l+1;
    //C语言中log默认以e为底,所有除以log2 
    int m = (int)(log((double)len) / log(2.0));
    int minn = min(Min_dp2[l][m],Min_dp2[r-(1<<m)+1][m]);
    return minn;
}
int main() {
	int q;
	cin >> q;
	for(int i = 1; i <= q; i++) {
		cin >> n >> k;
		for(int j = 1; j <= k; j++) {
			cin >> nd[j].a;
		}
		for(int j = 1; j <= k; j++) {
			cin >> nd[j].t;
		}
		sort(nd + 1, nd + k + 1, cmp);
		for(int j = 1; j <= k; j++) {
			a[j] = nd[j].a;
		}
		for(int j = 1; j <= k; j++) {
			t[j] = nd[j].t;
		}
		for(int j = 1; j <= k; j++) {
			f1[j] = a[j] + t[j];
			f2[j] = t[j] - a[j];
		}
		RMQ1(k);
		RMQ2(k);
		for(int i = 1; i <= n; i++) {
			int pos1 = lower_bound(a + 1, a + k + 1, i) - a;
			int pos2 = pos1 - 1;
			//1 ~ pos1 查询f2的最小值再加i pos2 ~ n 查询f1的最小值 再减i  这两者取min
			int ans = 0x3f3f3f3f;
			if(pos2 >= 1 && pos2 <= k) ans = min(ans, query2(1, pos2) + i);
			if(pos1 >= 1 && pos1 <= k) ans = min(ans, query1(pos1, k) - i);
			cout << ans << " ";
		}
		cout << endl;
	}
	return 0;
}

看别人的代码还有用优先队列做的,不明觉厉

Codeforces Round #731 (Div. 3) E. Air Conditioners(思维/DP/二分/区间最值/好题)

上一篇:242. 有效的字母异位词


下一篇:关于win server中 task Scheduler使用