题意:
神龙可以在没有下雨的时候喝掉一湖水, 一开始所有河都有水,另外,如果一个湖已经有水了,再下雨,这个湖就会闹水灾,如果一个湖原本没水,下雨了,就满水了,此时不会闹水灾,问是否可以做到不闹水灾,如果可以输出“YES”,且输出不下雨天喝哪河的水,也可以不喝水,这个时候输出0,否则输出“NO”
分析:
紫书上说需要优化算法 看到1e6的数据,很自然的想到nlogn的算法
怎么样才可以nlogn呢?
最好是保存每个节点之前下雨的那个相同点 例如 0 0 1 0 1
比如1湖在第三天和第五天都下雨了
那么 pre[1] = 3
由于一开始水都是满的 因此 pre[1] = 0 表示第0天每个湖都是满水的(下雨了)
每一次把对应湖的上次pre保存
这样需要On的时间
当第三天的时候这个时候置 pre[1] = 3
表明对接下来一个1湖下雨来说, 在第三天的时候下过了,也就是要找到从第三天到下一个一湖下雨天是否存在一个位置
好在我们在没下雨的时候把那个没下雨的天insert进去了,具体表现就是第四天的时候我们insert了一个4
这样在第五天的时候,发现从第三天二分查找一个位置有一个4可以。
那这样就行,顺便把4这个节点移除了
由于二分查找和set删除节点均为logn的时间,因此总时间可以在nlogn的时间内完成。
代码:
#include<bits/stdc++.h>
#define LL long long
#define ms(s) memset(s, 0, sizeof(s))
#define REP(i, a, b) for(int i = (a); i < (b); i++)
#define INF 0X7fffffff
using namespace std;
const int maxn = 1e6 + 10;
int rain[maxn];
int pre[maxn];
int ans[maxn];
int main() {
// freopen("in.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
ios::sync_with_stdio(false);
cin.tie(0);
int T;
cin >> T;
while(T--) {
set<int> s;
int n, m;
cin >> n >> m;
ms(pre), ms(ans);
bool flag = true;
REP(i, 0, m) cin >> rain[i];
REP(i, 0, m) {
if(rain[i] == 0) {
s.insert(i);
continue;
}
ans[i] = -1; //表示这一天不需要喝水
auto it = s.lower_bound(pre[rain[i]]);
if(it == s.end()) {
flag = false;
break;
}
pre[rain[i]] = i;
ans[*it] = rain[i];
s.erase(it);
}
if(!flag) {
cout << "NO" << endl;
continue;
}
bool first = true;
cout << "YES" << endl;
REP(i, 0, m) {
if(ans[i] == -1) continue;
if(first) cout << ans[i];
else cout << " " << ans[i];
first = false;
}
cout << endl;
}
return 0;
}

本文介绍了一种优化的湖水管理算法,通过使用预处理数组和集合数据结构,实现了在不下雨的日子里合理分配湖水,避免水灾的发生。该算法利用二分查找和set的特性,确保了整体操作在O(nlogn)的时间复杂度内完成。
&spm=1001.2101.3001.5002&articleId=103302730&d=1&t=3&u=05d72a1d4b5c4819926183e0028e9317)
213

被折叠的 条评论
为什么被折叠?



