前言

题目链接:洛谷Hydro & bzoj

题意简述

yzh 喜欢写 DS 题!你要维护一个环:

  1. 顺时针移动 \(k\) 位;
  2. 翻转 \(2 \sim n\);
  3. 交换 \(i\) 与 \(j\);
  4. 区间覆盖;
  5. 查询整个环有几个颜色段;
  6. 查询 \(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] 项链工厂 题解的更多相关文章

  1. BZOJ1493 [NOI2007]项链工厂

    未完待续... 终于改对了 热泪盈眶.jpg 错误原因:pushdown的时候没有判断是否有左右儿子,也没当x=0 return,于是出现一些奇怪的错误 #include<bits/stdc++ ...

  2. bzoj 1493: [NOI2007]项链工厂(线段树)

    1493: [NOI2007]项链工厂 Time Limit: 30 Sec  Memory Limit: 64 MBSubmit: 1256  Solved: 545[Submit][Status] ...

  3. 数据结构(Splay平衡树): [NOI2007] 项链工厂

    [NOI2007] 项链工厂 ★★★   输入文件:necklace.in   输出文件:necklace.out   简单对比 时间限制:4 s   内存限制:512 MB [问题描述] T公司是一 ...

  4. bzoj1493[NOI2007]项链工厂 线段树

    1493: [NOI2007]项链工厂 Time Limit: 30 Sec  Memory Limit: 64 MBSubmit: 1712  Solved: 723[Submit][Status] ...

  5. BZOJ_1493_[NOI2007]项链工厂_Splay

    BZOJ_1493_[NOI2007]项链工厂_Splay Description T公司是一家专门生产彩色珠子项链的公司,其生产的项链设计新颖.款式多样.价格适中,广受青年人的喜爱. 最近T公司打算 ...

  6. 1493: [NOI2007]项链工厂

    线段树. 真还就是个线段树.. 除去操作1,2的话,线段树很容易就处理了,问题在于如何处理操作1和2.(这点没想到).. 我们用一个delta维护操作1,如果没有旋转就+k,不然就-k. 每次读入i和 ...

  7. BZOJ1493 NOI2007 项链工厂 线段树模拟

    提交地址:http://www.lydsy.com/JudgeOnline/problem.php?id=1493 题目大意:给一个数列,进行一系列操作.包括旋转,翻转,改变等操作,以及查询颜色段数. ...

  8. NOI2007项链工厂——sbTreap代码

    #include <iostream> #include <cstdio> #include <algorithm> #include <cstring> ...

  9. NOI2007 项链工厂

    题目链接:戳我 60pts 有一点容易写错的小细节: 比如说求全局的段数的时候,如果只有一种颜色,那么当左右端点相等时,就不要ans--了. 注意右端点小于左端点的情况. #include<io ...

  10. 【BZOJ-1493】项链工厂 Splay

    1493: [NOI2007]项链工厂 Time Limit: 30 Sec  Memory Limit: 64 MBSubmit: 1440  Solved: 626[Submit][Status] ...

随机推荐

  1. vue3 父子组件间的传值通信

    1.父转子 // 父组件 <template> <div> <div> <p>{{ count }}</p> <Son :countF ...

  2. react 使用 error 报错

    在使用react 中报错原因总结 01 // Warning: Can't call setState on a component that is not yet mounted. This is ...

  3. http请求方式-OkHttpClient

    http请求方式-OkHttpClient import com.example.core.mydemo.http.OrderReqVO; import okhttp3.*; import org.s ...

  4. C#.NET与JAVA互通之DES加密V2024

    C#.NET与JAVA互通之DES加密V2024   配置视频:     环境: .NET Framework 4.6 控制台程序 JAVA这边:JDK8 (1.8) 控制台程序   注意点: 1.由 ...

  5. git 删除远程分支文件

    问题:多人协作开发同一分支的时候,有人误上传了一个不需要的文件,想删除远端仓库的该文件. 本地已经将此文件删除,推送至仓库时,仓库并未删除.此时拉取仓库更新本地时也不会将此文件拉取下来. 解决方案: ...

  6. pytest_terminal_summary重写收集测试报告并发送邮件,报错"Argument(s) {'Config'} are declared in the hookimpl but can not be found in the hookspec"

    步骤: 1.conftest.py文件,重写pytest_terminal_summary(terminalreporter, exitstatus, config) 2.run执行pytest.ma ...

  7. LLM技术全景图:技术人必备的技术指南,一张图带你掌握从基础设施到AI应用的全面梳理

    LLM技术全景图:技术人必备的技术指南,一张图带你掌握从基础设施到AI应用的全面梳理 LLM 技术图谱(LLM Tech Map)是将 LLM 相关技术进行系统化和图形化的呈现,此图谱主要特点是&qu ...

  8. Android ADB命令集锦

    Android ADB命令集锦 原文(有删改):https://blog.csdn.net/dianziagen/article/details/57400723 本文包括: adb基本指令 Shel ...

  9. 【简单总结】SLAM 算法的 Benchmark 及相关数据集的结果对比

    前言与参考 主要是copy一下总结,方便自己后续找方案特定使用,所有的出处均在标题处和原链接跳转,此处仅做各个benchmark收集使用,如果有原作者觉得侵权,请联系我 将全力配合相关内容和链接删除 ...

  10. js-内置函数-手稿