cf605D. Board Game(BFS 树状数组 set)
题意
有\(n\)张牌,每张牌有四个属性\((a, b, c, d)\),主人公有两个属性\((x, y)\)(初始时为(0, 0))
一张牌能够被使用当且仅当\(a < x, b < y\),使用后\(x\)会变为\(c\),\(y\)会变为\(d\)
问使用第\(n\)张牌的最小步数
Sol
直接从\((0, 0)\)开始大力BFS,那么第一次到达时就是最小的,同时记录一下前驱
现在的问题就是如何知道哪些点可以选,也就是找到所有\(a < x, b < y\)的点,可以直接树状数组+set维护
由于保证了每个元素只出现一次,因此总复杂度为\(O(nlog^2n)\)
#include<bits/stdc++.h>
#define Pair pair<int, int>
#define MP(x, y) make_pair(x, y)
#define fi first
#define se second
#define pb(x) push_back(x)
// #define int long long
#define LL long long
#define pt(x) printf("%d ", x);
#define Fin(x) {freopen(#x".in","r",stdin);}
#define Fout(x) {freopen(#x".out","w",stdout);}
using namespace std;
const int MAXN = 2e5 + 10, INF = 1e9 + 10, mod = 1e9 + 7;
const double eps = 1e-9;
void chmax(int &a, int b) {a = (a > b ? a : b);}
void chmin(int &a, int b) {a = (a < b ? a : b);}
int sqr(int x) {return x * x;}
int add(int x, int y) {if(x + y < 0) return x + y + mod; return x + y >= mod ? x + y - mod : x + y;}
void add2(int &x, int y) {if(x + y < 0) x = x + y + mod; else x = (x + y >= mod ? x + y - mod : x + y);}
int mul(int x, int y) {return 1ll * x * y % mod;}
inline int read() {
char c = getchar(); int x = 0, f = 1;
while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();}
while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
return x * f;
}
int N, a[MAXN], b[MAXN], c[MAXN], d[MAXN], vis[MAXN], dis[MAXN], pre[MAXN], da[MAXN], num;
#define lb(x) (x & (-x))
#define sit set<Pair>::iterator
set<Pair> T[MAXN];
void Add(int x, int v, int id) {
for(; x <= num; x += lb(x)) T[x].insert(MP(v, id));
}
vector<int> Query(int p) {
int x = a[p], y = b[p];
vector<int> res;
for(; x; x -= lb(x)) {
set<Pair> &now = T[x];
while(1) {
sit it = now.lower_bound(MP(y, 0));
if(it == now.end()) break;
res.pb(it -> se); now.erase(it);
}
}
return res;
}
void Des() {
sort(da + 1, da + num + 1); num = unique(da + 1, da + num + 1) - da - 1;
for(int i = 1; i <= N; i++) {
a[i] = num - (lower_bound(da + 1, da + num + 1, a[i]) - da) + 1;
c[i] = num - (lower_bound(da + 1, da + num + 1, c[i]) - da) + 1;
if(i != N) Add(c[i], d[i], i);
}
}
void print(int t) {
printf("%d\n", dis[t]);
for(int u = t; ~u; u = pre[u]) printf("%d ", u);
}
void BFS() {
queue<int> q; q.push(N); pre[N] = -1; dis[N] = 1;
while(!q.empty()) {
int p = q.front(); q.pop();
if(a[p] == num && !b[p]) {print(p); return ;}
vector<int> nxt = Query(p);
for(int i = 0, t; i < nxt.size(); i++) {
if(vis[nxt[i]]) continue; vis[nxt[i]] = 1;
q.push(t = nxt[i]);
dis[t] = dis[p] + 1, pre[t] = p;
}
}
puts("-1");
}
signed main() {
N = read(); bool flag = 0;
for(int i = 1; i <= N; i++) {
a[i] = read(), b[i] = read(), c[i] = read(), d[i] = read();
da[++num] = a[i];
da[++num] = c[i];
flag |= (!a[i] && !b[i]);
}
if(!flag) return puts("-1");
Des();
BFS();
return 0;
}
cf605D. Board Game(BFS 树状数组 set)的更多相关文章
- Codeforces 605D - Board Game(树状数组套 set)
Codeforces 题目传送门 & 洛谷题目传送门 事实上是一道非常容易的题 很容易想到如果 \(c_i\geq a_j\) 且 \(d_i\geq b_j\) 就连一条 \(i\to j\ ...
- bzoj1146整体二分+树链剖分+树状数组
其实也没啥好说的 用树状数组可以O(logn)的查询 套一层整体二分就可以做到O(nlngn) 最后用树链剖分让序列上树 #include<cstdio> #include<cstr ...
- 【树状数组(二叉索引树)】轻院热身—candy、NYOJ-116士兵杀敌(二)
[概念] 转载连接:树状数组 讲的挺好. 这两题非常的相似,查询区间的累加和.更新结点.Add(x,d) 与 Query(L,R) 的操作 [题目链接:candy] 唉,也是现在才发现这题用了这个知识 ...
- D 洛谷 P3602 Koishi Loves Segments [贪心 树状数组+堆]
题目描述 Koishi喜欢线段. 她的条线段都能表示成数轴上的某个闭区间.Koishi喜欢在把所有线段都放在数轴上,然后数出某些点被多少线段覆盖了. Flandre看她和线段玩得很起开心,就抛给她一个 ...
- csu 1757(贪心或者树状数组)
1757: 火车入站 Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 209 Solved: 51[Submit][Status][Web Board] ...
- Codeforces Gym 100269F Flight Boarding Optimization 树状数组维护dp
Flight Boarding Optimization 题目连接: http://codeforces.com/gym/100269/attachments Description Peter is ...
- gym 100589A queries on the Tree 树状数组 + 分块
题目传送门 题目大意: 给定一颗根节点为1的树,有两种操作,第一种操作是将与根节点距离为L的节点权值全部加上val,第二个操作是查询以x为根节点的子树的权重. 思路: 思考后发现,以dfs序建立树状数 ...
- BZOJ 2434 阿狸的打字机(ac自动机+dfs序+树状数组)
题意 给你一些串,还有一些询问 问你第x个串在第y个串中出现了多少次 思路 对这些串建ac自动机 根据fail树的性质:若x节点是trie中root到t任意一个节点的fail树的祖先,那么x一定是y的 ...
- BZOJ 1103: [POI2007]大都市meg [DFS序 树状数组]
1103: [POI2007]大都市meg Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 2221 Solved: 1179[Submit][Sta ...
随机推荐
- webpack快速入门——处理HTML中的图片
在webpack中是不喜欢你使用标签<img>来引入图片的,但是我们作前端的人特别热衷于这种写法, 国人也为此开发了一个:html-withimg-loader.他可以很好的处理我们在ht ...
- Android 打开系统设置界面及相应的系统界面
方法 1 :startActivity(new Intent(Settings.ACTION_WIFI_SETTINGS)); 方法 2:Intent intent = new Intent(&quo ...
- HTML+Javascript制作拼图小游戏详解(终)
上次我们已经讲解了制作的原理,并且展示了主要代码. 这次我将完整的代码给大家,仅供参考. HTML部分如下: <!DOCTYPE html> <html lang="en& ...
- Alamofire源码导读五:错误表示
AFError is the error type returned by Alamofire. It encompasses a few different types of errors, eac ...
- Linux必备命令
目录 概述 常用系统工作命令 系统状态检测命令 工作目录切换命令 文本文件 ...
- Ajax与XMLHttpRequest随笔
1.XMLHttpRequest对象 创建XHR对象:let xhr = new XMLHttpRequest(); open():启动一个请求准备发送 open()接收3个参数:请求类型('GET' ...
- 【洛谷P4934】 礼物,拓扑排序
题目大意:给你$n$个不重复的数,其值域为$[0,2^k)$,问你至少需要将这$n$个数拆成多少个集合,使得它们互相不是对方的子集,并输出方案. 数据范围:$n≤10^6$,$k≤20$. $MD$我 ...
- Linux开发端口的基本操作命令
Linux端口操作命令 查看开放端口:firewall-cmd --list-all 开发8080端口 --permanent 代码永久开发:firewall-cmd --add-port=8080/ ...
- Binder AIDL中自定义类型传递的源码分析
binder机制实现的IPC和共享内存的方式不同,它采取的是值拷贝的方式,即进程间传递的实体遵循Parcelable协议, Bp端负责向Parcel里写东西,Bn端负责从Parcel里读取还原,顺序是 ...
- Linux的文件的打包(tar方法)
Linux的文件的打包(tar方法) tar -c: 建立压缩档案 -x:解压 -t:查看内容 -r:向压缩归档文件末尾追加文件 -u:更新原压缩包中的文件 这五个是独立的命令,压缩解压都要用到其中一 ...