[BZOJ1171][BZOJ2892]大sz的游戏

试题描述

大sz最近在玩一个由星球大战改编的游戏。话说绝地武士当前共控制了N个星球。但是,西斯正在暗处悄悄地准备他们的复仇计划。绝地评议会也感觉到了这件事。于是,准备加派绝地武士到各星球防止西斯的突袭。一个星球受到攻击以后,会尽快通知到总基地。需要的时间越长的星球就需要越多绝地武士来防御。为了合理分配有限的武士,大sz需要你帮他求出每个星球各需要多少时间能够通知到总基地。由于某种原因,N个星球排成一条直线,编号1至N。其中总基地建在1号星球上。每个星球虽然都是绝地武士控制的,但是上面居住的生物不一定相同,并且科技水平也不一样。第i个星球能收到并分析波长在[xi, yi]之间的信号,并且也能够发出在这个区间的信号,但是不能发出其他任何波长的信号。由于技术原因,每个星球只能发信号到比自己编号小的距离不超过L的星球。特别地,强大的总基地可以接收任何波长的信号。每个星球处理接收到的数据需要1个单位时间,传输时间可以忽略不计。

输入

第一行两个正整数N、L。接下来N-1行,总共第i行包含了三个正整数xi、yi、li,其中li表示第i个星球距离1号星球li,满足li严格递增。

输出

总共N-1行,每行一个数分别表示2到N号星球至少需要多少单位时间,总基地能够处理好数据,如果无法传到总基地则输出-1。

输入示例1

3 1
1 2 1
2 3 2

输出示例1

1
2

输入示例2

3 3
1 2 1
2 3 2

输出示例2

1
1

数据规模及约定

30%的数据满足N <=20000;
100%的数据满足2 <=N<= 2.5*10^5、0<=xi,yi,li<=2*10^9,1<=L<=2*10^9,xi<=yi.

题解

首先这是一道裸 dp,f(i)表示对于星球 i 要求的答案,f(i) = min{ f(j) | [xi, yi]与[xj, yj]有交集 & l[i] - l[j] <= L & 0 < j < i } + 1.

最棘手的是两个区间有没有交集的问题。可以考虑离散后用线段树,但是要资瓷区间加入、删除、查询操作,不好搞,注意在上面的转移方程中,随着 i 的增长,j 所在的区间是一直向右移动的(因为 l[i] - l[j] <= L),或者说是一个滑动窗口,可以再套一个单调队列。

此外这里的线段树标记不好合并,所以干脆不进行标记下传;只在线段树的节点刚好被操作区间完全包含时,在这个节点上打标记,再向上更新一下最小值即可,询问时需要把节点到根的标记都取一个 min。(注意为什么这里我要把“标记”标红)

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <list>
using namespace std;

const int BufferSize = 1 << 16;
char buffer[BufferSize], *Head, *tail;
inline char Getchar() {
	if(Head == tail) {
		int l = fread(buffer, 1, BufferSize, stdin);
		tail = (Head = buffer) + l;
	}
	return *Head++;
}
int read() {
	int x = 0, f = 1; char c = Getchar();
	while(!isdigit(c)){ if(c == ‘-‘) f = -1; c = Getchar(); }
	while(isdigit(c)){ x = x * 10 + c - ‘0‘; c = Getchar(); }
	return x * f;
}

#define maxn 250005
#define oo 2147483646
int n, Len, num[maxn<<1], cnt, x[maxn], y[maxn], l[maxn], f[maxn], que[maxn], hd, tl;

list <int> Q[maxn<<3];
int res[maxn<<3];
void update(int L, int R, int o, int ql, int qr, int p, bool tp) {
	int M = L + R >> 1, lc = o << 1, rc = lc | 1;
	if(ql <= L && R <= qr) {
		if(!tp) {
			while(!Q[o].empty() && Q[o].front() <= p) Q[o].pop_front();
		}
		else {
			while(!Q[o].empty() && f[Q[o].back()] >= f[p]) Q[o].pop_back();
			Q[o].push_back(p);
		}
		res[o] = oo;
		if(!Q[o].empty()) {
			if(L < R) res[o] = min(res[lc], res[rc]);
			res[o] = min(res[o], f[Q[o].front()]);
		}
		else if(L < R) res[o] = min(res[lc], res[rc]);
		return ;
	}
	if(ql <= M) update(L, M, lc, ql, qr, p, tp);
	if(qr > M) update(M+1, R, rc, ql, qr, p, tp);
	res[o] = min(res[lc], res[rc]);
	if(!Q[o].empty()) res[o] = min(res[o], f[Q[o].front()]);
	return ;
}
int query(int L, int R, int o, int ql, int qr) {
	if(ql <= L && R <= qr) return res[o];
	int M = L + R >> 1, lc = o << 1, rc = lc | 1, ans = oo;
	if(ql <= M) ans = min(ans, query(L, M, lc, ql, qr));
	if(qr > M) ans = min(ans, query(M+1, R, rc, ql, qr));
	if(!Q[o].empty()) ans = min(ans, f[Q[o].front()]);
	return ans;
}

int main() {
	n = read(); Len = read();
	for(int i = 2; i <= n; i++) {
		num[++cnt] = x[i] = read(); num[++cnt] = y[i] = read();
		l[i] = read();
	}
	sort(num + 1, num + cnt + 1);
	for(int i = 2; i <= n; i++) {
		x[i] = lower_bound(num + 1, num + cnt + 1, x[i]) - num;
		y[i] = lower_bound(num + 1, num + cnt + 1, y[i]) - num;
	}

	for(int i = 0; i < (maxn<<3); i++) res[i] = oo;
	que[++tl] = 1;
	f[1] = 0; x[1] = 1; y[1] = cnt; l[1] = 0;
	update(1, cnt, 1, 1, cnt, 1, 1);
	for(int i = 2; i <= n; i++) {
		while(hd < tl && l[que[hd+1]] < l[i] - Len) {
			hd++;
			update(1, cnt, 1, x[que[hd]], y[que[hd]], que[hd], 0);
		}
		f[i] = query(1, cnt, 1, x[i], y[i]) + 1;
		if(f[i] < oo) {
			printf("%d\n", f[i]);
			que[++tl] = i;
			update(1, cnt, 1, x[i], y[i], i, 1);
		}
		else puts("-1");
	}

	return 0;
}
/*
3 3
1 2 1
2 3 2

8 100000
2 8192813 100000
5 23131346 113213
23131346 83131346 123213
23131346 83131346 199213
231346 103131346 213213
213 1038 213214
854 5432153 214214
*/
时间: 2024-10-11 16:04:11

[BZOJ1171][BZOJ2892]大sz的游戏的相关文章

【BZOJ-2892&amp;1171】强袭作战&amp;大sz的游戏 权值线段树+单调队列+标记永久化+DP

2892: 强袭作战 Time Limit: 50 Sec  Memory Limit: 512 MBSubmit: 45  Solved: 30[Submit][Status][Discuss] Description 在一个没有冬马的世界里,经历了学园祭后的春希着急着想要见到心爱的雪菜.然而在排队想见雪菜的fans太多了,春希一时半会凑不到雪菜面前. 作为高帅富,这样的问题怎么能难倒春希?春希从武也手中拿到了取自金闪闪宝库里的多啦A梦的传话筒,并且给每一个排队的fans都发了一个传话筒. 于

bzoj 1171 大sz的游戏&amp; 2892 强袭作战 (线段树+单调队列+永久性flag)

大sz的游戏 Time Limit: 50 Sec  Memory Limit: 357 MBSubmit: 536  Solved: 143[Submit][Status][Discuss] Description 大sz最近在玩一个由星球大战改编的游戏.话说绝地武士当前共控制了N个星球.但是,西斯正在暗处悄悄地准备他们的复仇计划.绝地评议会也感觉到了这件事.于是,准备加派绝地武士到各星球防止西斯的突袭.一个星球受到攻击以后,会尽快通知到总基地.需要的时间越长的星球就需要越多绝地武士来防御.为

BZOJ1171: 大sz的游戏&amp;BZOJ2892: 强袭作战

Description 大sz最近在玩一个由星球大战改编的游戏.话说绝地武士当前共控制了N个星球.但是,西斯正在暗处悄悄地准备他们的复仇计划.绝地评议会也感觉到了这件事.于是,准备加派绝地武士到各星球防止西斯的突袭.一个星球受到攻击以后,会尽快通知到总基地.需要的时间越长的星球就需要越多绝地武士来防御.为了合理分配有限的武士,大sz需要你帮他求出每个星球各需要多少时间能够通知到总基地.由于某种原因,N个星球排成一条直线,编号1至N.其中总基地建在1号星球上.每个星球虽然都是绝地武士控制的,但是上

BZOJ1171 : 大sz的游戏

f[i]=min(f[j])+1,线段j与线段i有交,且l[i]-l[j]<=L. 线段j与线段i有交等价于y[j]>=x[i],x[j]<=y[i]. 因为l[i]递增,所以可以维护一个单调递增的j,表示[j,i-1]范围内都可以更新f[i]. 用k-d树动态维护即可,时间复杂度$O(n\sqrt{n})$. #include<cstdio> #include<algorithm> const int N=250010,inf=2000000000; int n

1353 大神的游戏

1353 大神的游戏 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题解 题目描述 Description 在那遥远的机房,有一片神奇的格子.为了方便起见,我们编号为1~n.传说只要放入一些卡片,就能实现愿望.卡片一共有m种颜色,但是相邻的格子间不能放入相同颜色的卡片.只要不重复的摆出所有组合,就能召唤出神汉堡 @解决掉你 大神,为你实现梦想.从古书中翻出这个记载的shc同学,便日以夜继的摆起了他的卡片.现在他想知道一共有多少种不同的组合不合法,以便算出愿望实

大嘴鱼游戏

设计小组: 066季忠祥 048李春晓 项目名称:大嘴鱼吃豆子 编程语言:Java 要求: 设计一款休闲小游戏,大嘴鱼吃豆子.要求操作简单,有简单介绍和操作方法. 游戏说明: 大嘴鱼游戏的简单使用说明:使用键盘上的上.下.左.右控制大嘴鱼的方向,每吃1条小鱼,得分加1分.每吃10条小鱼,大嘴鱼将升级:大小加1,速度加2. 二.截图 三.约定规范 代码写清注释 注意段落缩进 更改代码要做记录 四.时间记录 项目选题:2小时 设计思路:1天 明确分工:2小时 代码编写:2天 测试:3小时 上传代码:

[知了堂学习笔记]_用JS制作《飞机大作战》游戏_第1讲(素材查找和界面框架搭建)

一.查找素材: 二.分析游戏界面框架: 登录界面.游戏界面.暂停游戏界面.玩家死亡后弹出界面:并对应的界面包含什么元素: 三.分别搭建以上四个界面: 1.登录界面与游戏界面框架(隐藏游戏界面,四个界面的宽度和高度要一致): HTML代码: <!--main div是游戏界面的大DIV --> <div id="main" style="height: 643px;"> <!--玩家头像DIV--> <div id="

[知了堂学习笔记]_用JS制作《飞机大作战》游戏_第2讲(四大界面之间的跳转与玩家飞机的移动)

一.通过点击按钮事件,实现四大界面之间的跳转: (一)跳转的思路: 1.打开软件,只显示登录界面(隐藏游戏界面.暂停界面.玩家死亡界面) 2.点击微信登录(QQ登录)跳转到游戏界面,隐藏登录界面 3.点击暂停,弹出具有透明度的暂停界面 4.点击暂停界面的开始按钮,隐藏暂停界面,调用开始方法(点击登录跳转的方法): 5.点击暂停界面的退出游戏,只显示登录界面,隐藏其他界面: 6.游戏结束界面,该界面的跳转目前还不能通过游戏实现,可以先建设(根据上一讲的游戏界面图片制作). 7.点击游戏结束界面的开

刺猬大作战(游戏引擎用Free Pascal写成,GUI用C++写成,使用SDL和Qt4)

游戏特性[编辑] 游戏引擎用Free Pascal写成,GUI用C++写成,使用SDL和Qt4[2]. 0.9.12开始支持实时动态缩放游戏画面. 个性化[编辑] 刺猬大作战有着高度定制性 游戏模式:游戏方式可以发生很大变化,比如棒球模式中,所有刺猬都有保护膜无法损伤,只能击入水中退场 可以制作语音,游戏已经包括如海盗,唱诗风格等五种风格,使用开放的ogg格式 纸娃娃系统,不只可以为每个队员命名,还可以用头饰分辨每个人,已有超过90种头部装饰分辨每个刺猬 支持定制团队背景和离场的动画效果 武器[