[NOI2007] 项链工厂 题解
前言
题目链接:洛谷;Hydro & bzoj。
题意简述
yzh 喜欢写 DS 题!你要维护一个环:
- 顺时针移动 \(k\) 位;
- 翻转 \(2 \sim n\);
- 交换 \(i\) 与 \(j\);
- 区间覆盖;
- 查询整个环有几个颜色段;
- 查询 \(i \sim j\) 有几个颜色段。
题目分析
平衡树板子啊,代码很好写,\(273\) 行。但是为什么不使用线段树呢?
发现,顺时针移位,原本该连续的区间也还在一块(这里指的是环上,在序列上可能一个在首一个在尾,但这对分析问题并不重要)。所以遇到移位操作,只用记录一个偏移量,查询的时候对下表进行相应处理即可。同理,翻转操作也不必真的进行翻转,只用记一个翻转标记,每次让它异或 \(1\) 即可。我们可以轻松写出如下转换函数。
auto trans = [&mov, &flip] (int x) -> int {
if (flip) x = mov - x + 2;
else x = x - mov;
x = (x % n + n) % n;
return x ? x : n;
};
接下来考虑线段树如何实现。我们发现,问题变成了区间覆盖、单点查询颜色、区间查询颜色段数。很套路,在信息中记录左右端点的颜色以及区间内的颜色段数。合并的时候把两个自区间颜色段数相加,如果左边的右端点和右边的左端点颜色相同,再减去一次重复算的这一次。
struct Info {
int l, r, cnt;
friend Info operator + (const Info& a, const Info& b) {
return { a.l, b.r, a.cnt + b.cnt - (a.r == b.l) };
}
};
剩下的板子不展开。
代码
// #pragma GCC optimize(3)
// #pragma GCC optimize("Ofast", "inline", "-ffast-math")
// #pragma GCC target("avx", "sse2", "sse3", "sse4", "mmx")
#include <iostream>
#include <cstdio>
#define debug(a) cerr << "Line: " << __LINE__ << " " << #a << endl
#define print(a) cerr << #a << "=" << (a) << endl
#define file(a) freopen(#a".in", "r", stdin), freopen(#a".out", "w", stdout)
#define main Main(); signed main() { return ios::sync_with_stdio(0), cin.tie(0), Main(); } signed Main
using namespace std;
int n, m, col[500010];
struct Segment_Tree {
#define lson (idx << 1 )
#define rson (idx << 1 | 1)
struct Info {
int l, r, cnt;
friend Info operator + (const Info& a, const Info& b) {
if (a.l == -1) return b;
if (b.l == -1) return a;
return { a.l, b.r, a.cnt + b.cnt - (a.r == b.l) };
}
};
struct node {
int l, r;
int tag;
Info info;
} tree[500010 << 2];
void build(int idx, int l, int r) {
tree[idx] = {l, r, -1, {0, 0, 0}};
if (l == r) return tree[idx].info = {col[l], col[r], 1}, void();
int mid = (l + r) >> 1;
build(lson, l, mid);
build(rson, mid + 1, r);
tree[idx].info = tree[lson].info + tree[rson].info;
}
void pushtag(int idx, int tag) {
tree[idx].tag = tag;
tree[idx].info = {tag, tag, 1};
}
void pushdown(int idx) {
if (tree[idx].tag == -1) return;
pushtag(lson, tree[idx].tag);
pushtag(rson, tree[idx].tag);
tree[idx].tag = -1;
}
void modify(int idx, int l, int r, int tag) {
if (tree[idx].l > r || tree[idx].r < l) return;
if (l <= tree[idx].l && tree[idx].r <= r) return pushtag(idx, tag);
pushdown(idx);
modify(lson, l, r, tag);
modify(rson, l, r, tag);
tree[idx].info = tree[lson].info + tree[rson].info;
}
Info query(int idx, int l, int r) {
if (tree[idx].l > r || tree[idx].r < l) return {-1, -1, 0};
if (l <= tree[idx].l && tree[idx].r <= r) return tree[idx].info;
pushdown(idx);
return query(lson, l, r) + query(rson, l, r);
}
#undef lson
#undef rson
} yzh;
#ifdef XuYueming
#define printf printf(">>> "), printf
#endif
signed main() {
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; ++i)
scanf("%d", &col[i]);
scanf("%d", &m), yzh.build(1, 1, n);
for (int i, j, c, k, mov = 0, flip = 0; m--; ) {
static char op[10];
static auto trans = [&mov, &flip] (int x) -> int {
if (flip) x = mov - x + 2;
else x = x - mov;
x = (x % n + n) % n;
return x ? x : n;
};
scanf("%s", op);
if (*op == 'R') {
scanf("%d", &k);
mov = (mov + k) % n;
} else if (*op == 'F') {
flip ^= 1, mov = (n - mov) % n;
} else if (*op == 'S') {
scanf("%d%d", &i, &j);
i = trans(i), j = trans(j);
int ci = yzh.query(1, i, i).l, cj = yzh.query(1, j, j).l;
yzh.modify(1, i, i, cj), yzh.modify(1, j, j, ci);
} else if (*op == 'P') {
scanf("%d%d%d", &i, &j, &c);
i = trans(i), j = trans(j);
if (flip) swap(i, j);
if (i <= j) {
yzh.modify(1, i, j, c);
} else {
yzh.modify(1, i, n, c);
yzh.modify(1, 1, j, c);
}
} else if (op[1] == '\0') {
printf("%d\n", max(1, yzh.tree[1].info.cnt - (yzh.tree[1].info.l == yzh.tree[1].info.r)));
} else {
scanf("%d%d", &i, &j);
i = trans(i), j = trans(j);
if (flip) swap(i, j);
if (i <= j) {
printf("%d\n", yzh.query(1, i, j).cnt);
} else {
printf("%d\n", (yzh.query(1, i, n) + yzh.query(1, 1, j)).cnt);
}
}
}
return 0;
}
后记 & 反思
没有敏锐地发现连续段在操作后还是连续的这一性质,导致没秒掉这道水题。
[NOI2007] 项链工厂 题解的更多相关文章
- BZOJ1493 [NOI2007]项链工厂
未完待续... 终于改对了 热泪盈眶.jpg 错误原因:pushdown的时候没有判断是否有左右儿子,也没当x=0 return,于是出现一些奇怪的错误 #include<bits/stdc++ ...
- bzoj 1493: [NOI2007]项链工厂(线段树)
1493: [NOI2007]项链工厂 Time Limit: 30 Sec Memory Limit: 64 MBSubmit: 1256 Solved: 545[Submit][Status] ...
- 数据结构(Splay平衡树): [NOI2007] 项链工厂
[NOI2007] 项链工厂 ★★★ 输入文件:necklace.in 输出文件:necklace.out 简单对比 时间限制:4 s 内存限制:512 MB [问题描述] T公司是一 ...
- bzoj1493[NOI2007]项链工厂 线段树
1493: [NOI2007]项链工厂 Time Limit: 30 Sec Memory Limit: 64 MBSubmit: 1712 Solved: 723[Submit][Status] ...
- BZOJ_1493_[NOI2007]项链工厂_Splay
BZOJ_1493_[NOI2007]项链工厂_Splay Description T公司是一家专门生产彩色珠子项链的公司,其生产的项链设计新颖.款式多样.价格适中,广受青年人的喜爱. 最近T公司打算 ...
- 1493: [NOI2007]项链工厂
线段树. 真还就是个线段树.. 除去操作1,2的话,线段树很容易就处理了,问题在于如何处理操作1和2.(这点没想到).. 我们用一个delta维护操作1,如果没有旋转就+k,不然就-k. 每次读入i和 ...
- BZOJ1493 NOI2007 项链工厂 线段树模拟
提交地址:http://www.lydsy.com/JudgeOnline/problem.php?id=1493 题目大意:给一个数列,进行一系列操作.包括旋转,翻转,改变等操作,以及查询颜色段数. ...
- NOI2007项链工厂——sbTreap代码
#include <iostream> #include <cstdio> #include <algorithm> #include <cstring> ...
- NOI2007 项链工厂
题目链接:戳我 60pts 有一点容易写错的小细节: 比如说求全局的段数的时候,如果只有一种颜色,那么当左右端点相等时,就不要ans--了. 注意右端点小于左端点的情况. #include<io ...
- 【BZOJ-1493】项链工厂 Splay
1493: [NOI2007]项链工厂 Time Limit: 30 Sec Memory Limit: 64 MBSubmit: 1440 Solved: 626[Submit][Status] ...
随机推荐
- linux elasticsearch-8.2.0安装
1.下载,解压缩,命令行前不要留空格 官网下载地址: https://www.elastic.co/cn/downloads/elasticsearch https://artifacts.elast ...
- SingletonKit单例源码阅读学习
阅读学习QFramwork中的SingletonKit源码. Singleton 普通类的单例 作为最常用的单例模块,通过继承单例泛型类来实现,需要私有构造: //使用第一种接口单例方式 intern ...
- poj1163 the triangle 题解
Description 7 3 8 8 1 0 2 7 4 4 4 5 2 6 5 (Figure 1) Figure 1 shows a number triangle. Write a progr ...
- CLR via C# 笔记 -- 可空值类型(19)
1. 值类型的变量永远不会为null,所有需要使用System.Nullable<T> 2. 操作数是null,结构是null:==.!=操作数都为null,则返回true:<.&g ...
- 15-BFC
01 BFC官方解释 https://www.w3.org/TR/CSS2/visuren.html#normal-flow 大致意思如下 02 什么情况下会形成BFC MDN解释 https://d ...
- 基于RK3588的NPU案例分享!6T是真的强!
RK3588 NPU简介 作为瑞芯微新一代旗舰工业处理器,RK3588 NPU性能可谓十分强大,6TOPS设计能够实现高效的神经网络推理计算.这使得RK3588在图像识别.语音识别.自然语言处理等人工 ...
- 小组合作实现的基于 jsp,servlet,mysql 编写的学校管理系统
基本完成的页面--源代码在<文件>中可下载 文件地址:https://i.cnblogs.com/Files.aspx 学生管理模块各功能已实现 百度网盘下载地址: 链接:https:// ...
- oeasy教您玩转vim - 55 - # 参数替换
[Github地址] (https://github.com/overmind1980/oeasyvim) [Gitee地址] (overmind1980/oeasyvim) [蓝桥实验楼 邀请码 ...
- Prometheus 基于Python Django实现Prometheus Exporter
基于Python Django实现Prometheus Exporter 需求描述 运行监控需求,需要采集Nginx 每个URL请求的相关信息,涉及两个指标:一分钟内平均响应时间,调用次数,并且为每个 ...
- 阅读翻译Mathematics for Machine Learning之2.7 Linear Mappings
阅读翻译Mathematics for Machine Learning之2.7 Linear Mappings 关于: 首次发表日期:2024-07-23 Mathematics for Machi ...