您的位置:首页 > 其它

【BZOJ3827】[Poi2014]Around the world【尺取法】【并查集】

2016-04-14 22:56 337 查看
【题目链接】

对于每个询问,设油量为d。

先预处理出每个点走一次最多走到哪,这个用尺取法可以O(n)。

然后得到一颗树,算一下每个点的深度。

枚举起点,在树上一直向上爬,直到距离超过n,爬的过程同时用并查集合并。

傻逼题卡内存。

/* Pigonometry */
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

const int maxn = 1000005, inf = 0x7FFFFFFF;

int n, m, dis[maxn], next[maxn << 1], depth[maxn << 1];

inline int iread() {
int f = 1, x = 0; char ch = getchar();
for(; ch < '0' || ch > '9'; ch = getchar()) f = ch == '-' ? -1 : 1;
for(; ch >= '0' && ch <= '9'; ch = getchar()) x = x * 10 + ch - '0';
return f * x;
}

inline int solve(int x) {
int fa = x;
for(; fa < x + n; fa = next[fa]);
for(int i = next[x], j = x; i != fa; j = i, i = next[i]) next[j] = fa;
return depth[x] - depth[fa];
}

int main() {
n = iread(); m = n << 1;
int k = iread(), lwb = 0;
for(int i = 1; i <= n; i++) {
dis[i] = iread();
lwb = max(lwb, dis[i]);
}
while(k--) {
int d = iread();
if(d < lwb) {
printf("NIE\n");
continue;
}
for(int i = 1, j = 1, sum = 0; i <= m; i++) {
while(j < m)
if(sum + dis[j > n ? j - n : j] <= d) {
sum += dis[j > n ? j - n : j];
j++;
}
else break;
sum -= dis[i > n ? i - n : i];
next[i] = j;
}
depth[m] = 0;
for(int i = m; i >= 1; i--) depth[i] = depth[next[i]] + 1;
int ans = inf;
for(int i = 1; i <= n; i++) ans = min(ans, solve(i));
printf("%d\n", ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: