【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;
}
对于每个询问,设油量为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;
}
相关文章推荐
- 为什么要有uboot
- 计算php脚本执行时间
- 关于IOS生命周期和设计模式
- CodeForces 622B The Time
- java连接数据库时jdbc设置编码-jdbc-oracle-字符编码
- HDU_2586_How far away ?_MLE_floyd
- CodeForces 622A Infinite Sequence
- Ruby notes #1 Environment setup on Win32 platform
- 邮箱伪造详解2013-10-04
- NSOperation
- 结队--复利计算再升级
- 《Linux内核分析》第八周笔记 进程的切换和系统的一般执行过程
- NSUserDefaults-01
- 0414复利计算6.0-----结对编程
- iOS 数据序列化,NSCoding, NSCoder
- Apache+Tomcat+AJP
- PHP——数组函数_学习笔记
- PHP基础语法
- 错排公式(转)
- poj 1459 Power Network 最大流