A(巧妙使用并查集)
题意:
共1e6个位置,q次操作,每次让第 i 个位置坐人或者查询 [l,r] 区间的最小编号的人
(1<=i, q<=1e6)
题解:
如果把每个有人的位置指向自己,把没有人的位置指向下一个位置,那么每次查询相当于是查询一次l的根节点。所以把询问离线存下来维护一个并查集即可。注意每次查询需要在O(1)的时间内才可以。
注
使用FastIO的输入挂后,cout,printf等输出函数可能不会将输出显示到控制台中,调试过后直接交就可以。
表示原本2.1s超时,把输出的cout改成printf后,瞬间变成0.5s
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e6+10;
int fa[maxn];
int ans[maxn];
namespace fastIO {
#define BUF_SIZE 100000
bool IOerror = 0;
inline char nc() {
static char buf[BUF_SIZE], *p1 = buf + BUF_SIZE, *pend = buf + BUF_SIZE;
if(p1 == pend) {
p1 = buf;
pend = buf + fread(buf, 1, BUF_SIZE, stdin);
if(pend == p1) {
IOerror = 1;
return -1;
}
}
return *p1++;
}
inline bool blank(char ch) {
return ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t';
}
inline void read(int &x) {
char ch;
while(blank(ch = nc()));
if(IOerror)
return;
for(x = ch - '0'; (ch = nc()) >= '0' && ch <= '9'; x = x * 10 + ch - '0');
}
#undef BUF_SIZE
};
int find_fa(int x){
if(x == fa[x]) return x;
return fa[x] = find_fa(fa[x]);
}
struct operate{
int x, y, z;
}op[maxn];
int main()
{
int T; fastIO::read(T);
int cas = 1;
int cnt = 0;
while(T--){
int opn;
fastIO::read(opn);
//cin >> opn;
cnt = 0;
for(int i = 0; i < maxn; i++) fa[i] = i+1;
fa[maxn-1] = maxn-1;
for(int i = 0; i < opn; i++){
//cin >> op[i].x >> op[i].y;
fastIO::read(op[i].x);
fastIO::read(op[i].y);
if(op[i].x == 2)
fastIO::read(op[i].z);
//cin >> op[i].z;
else fa[op[i].y] = op[i].y;
}
while(opn--){
if(op[opn].x == 1){
int y = op[opn].y;
fa[y] = y+1;
}
else{
int f = find_fa(op[opn].y);
if(f > op[opn].z) ans[++cnt] = -1;
else ans[++cnt] = f;
}
}
printf("Case #%d:\n", cas++);
while(cnt)
printf("%d\n", ans[cnt--]);
//cout << ans[cnt--] << endl;
}
return 0;
}
J
题意:
已知n个城市的位置,有个毒圈从1号城市开始缩,要求人在某一个时刻前跑进某一个城市。每个城市有一个物品,捡起它需要花费一定时间,求出从1安全抵达n最多能捡多少物品。
题解
非常有趣的水题。非常显然的贪心是能捡就捡,但是这样存在的问题是可能捡了一个时间花费多的导致后面时间花费少的不能捡了。所以用优先队列维护捡
了的物品,每次到一个城市都把里面的物品捡起来,然后如果不能安全到达下一个城市的话就把队列中花费最久的“反悔”掉,这样可以保证是最优的并且是安全的。时间复杂度O(nlgn)
待查错
#include <bits/stdc++.h>
using namespace std;
int n;
const int maxn = 2e5+10;
int l[maxn], t[maxn], p[maxn];
int main()
{
int T; cin >> T;
int cas = 1;
while(T--){
priority_queue<int, vector<int>, greater<int> > que;
while(!que.empty()) que.pop();
cin >> n;
for(int i = 0; i < n; i++) scanf("%d", &l[i]);
for(int i = 0; i < n; i++) scanf("%d", &t[i]);
for(int i = 0; i < n-1; i++) scanf("%d", &p[i]);
int cur = 0;
for(int i = 0; i < n-1; i++){
cur += p[i]; que.push(p[i]);
while(cur+l[i+1]-l[i]>t[i+1]){
int q = que.top();
cur-=q; que.pop();
}
cur += l[i+1]-l[i];
}
printf("Case #%d: %d\n", cas++, que.size());
}
return 0;
}