前言

题目链接:洛谷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. PIC18 bootloader之RS485 bootloader

                                  了解更多关于bootloader 的C语言实现,请加我Q扣: 1273623966 (验证信息请填 bootloader),欢迎咨询或定制b ...

  2. idea部署运行tomcat项目方法

    在导航栏点击Add Configuration-或者(打开菜单Run->Edit Configuration) 点击+号,选择Tomcat Server ->选择Local->在Na ...

  3. 如何使用JavaScript实现在线Excel附件的上传与下载?

    前言 在本地使用Excel时,经常会有需要在Excel中添加一些附件文件的需求,例如在Excel中附带一些Word,CAD图等等.同样的,类比到Web端,现在很多人用的在线Excel是否也可以像本地一 ...

  4. 实验五:FTP远程密码pojie(有敏感词)

    [实验目的] 了解远程FTP密码pojie原理,了解如何有效防范类似攻击的方法和措施,掌握pojieftp帐号口令pojie技术的基本原理.常用方法及相关工具. [知识点] FTP口令pojie [实 ...

  5. [flask]统一API响应格式

    前言 在设计API返回内容时,通常需要与前端约定好API返回响应体内容的格式.这样方便前端进行数据反序列化时相应的解析处理,也方便其它服务调用.不同公司有不同的响应内容规范要求,这里以常见的JSON响 ...

  6. 记一次反向代理过滤sql注入

    公司有一php系统,由于该系统是购买的,并且没人懂php,无法通过修改代码过滤sql注入问题 代码如下: public class Program { public static void Main( ...

  7. ReST,以及RESTful的 简单介绍

    什么是 ReST 阮一峰说的比较清楚,具体见他的博客文章. 二.名称 ReST这个词,是[Roy Thomas Fielding](http://en.wikipedia.org/wiki/Roy_F ...

  8. 统信 UOS 重置Root账号密码 获取 Root 权限

    统信服务器默认无法用root 账号登入系统,用普通管理员登入后在切换至root账户下即可,初次使用系统时 切换至root账户前需要做很多配置 1.同信切换root账户首先要激活下系统,可以选择试用期激 ...

  9. Quarkus初体验:动态加载和原生部署

    在前面的文章<尝试官方的第一个SpringNative 0.11程序>中提到过Quarkus这门技术.这里就简单演示一下它的两个主要功能:Live Coding和Native Build. ...

  10. AT_abc317_f 题解

    调了一小时结果发现爆 long long 了. 考虑数位 dp,具体来说,设计状态 \(dp_{i,r_1,r_2,r_3,mx_1,mx_2,mx3_,c_1,c_2,c_3}\) 表示当前考虑到第 ...