正题

题目链接:https://www.luogu.org/problemnew/show/P4130


题目大意

一个环形颜色珠子链,位置(注意不是上面的珠子)从最上顺时针下来位置依次标号1∼n1\sim n1∼n。

然后要求支持以下操作

  1. Rk:R\ k:R k:将所有珠子顺时针旋转kkk个。
  2. F:F:F:将所有珠子以111向下翻转
  3. Sij:S\ i\ j:S i j:交换iii和jjj上的珠子
  4. Pijk:P\ i\ j\ k:P i j k:将iii顺时针到jjj的珠子都涂上颜色kkk
  5. C:C:C:询问整个链有多少颜色段
  6. CSij:CS\ i\ j:CS i j:询问iii顺时针到jjj有多少颜色段。

(颜色段为连续的相同颜色)


解题思路

先不考虑前两个操作,我们可以用线段树进行操作。

储存[l,r,w,lc,rc,lazy][l,r,w,lc,rc,lazy][l,r,w,lc,rc,lazy]分别表示下标l∼rl\sim rl∼r,有www个颜色段,头颜色为lclclc,尾颜色为rcrcrc,懒惰标签lazylazylazy

然后我们可以利用lc,rclc,rclc,rc进行合并。

之后我们就可以轻易的实现后4个操作。

那我们考虑前两个操作,我们会发现它并不会破坏连续性,也就是任何一个位置相邻的两个位置的数字编号也与其相邻。

那么我们就可以使用一个十分优秀的算法,我们用ttt记录其旋转了几步,然后用BBB记录是否翻转(因为翻转两次等于没有翻转)。之后就可以计算出给出的数字段旋转和翻转之前应该在哪个位置。
然后照样计算就好了。


codecodecode

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=500100;
struct Tree_node{int l,r,w,lc,rc,lazy;
}ans;
int n,C,m,t,B;
struct Line_cut_tree{Tree_node t[N<<2];
//  node merge(node tl,node tr)
//  {//      node t;
//      t.w=tl.w+tr.w+(tl.rc!=tr.lc);
//      return t;
//  }void megre(Tree_node &t,Tree_node tl,Tree_node tr){t.lc=tl.lc;t.rc=tr.rc;t.w=tl.w+tr.w-(tl.rc==tr.lc);}void build(int x,int l,int r){t[x].l=l;t[x].r=r;if(l==r){scanf("%d",&t[x].lc); t[x].rc=t[x].lc;t[x].w=1;return;}int mid=(l+r)/2;build(x*2,l,mid);build(x*2+1,mid+1,r);megre(t[x],t[x*2],t[x*2+1]);}void downdata(int x){if(!t[x].lazy) return;t[x*2].lazy=t[x*2+1].lazy=t[x].lazy;t[x*2].w=t[x*2+1].w=1;t[x*2].lc=t[x*2].rc=t[x*2+1].lc=t[x*2+1].rc=t[x].lazy;t[x].lazy=0;}void Ask(int x,int l,int r){if(t[x].l==l&&t[x].r==r){if(!ans.rc) ans.lc=t[x].lc;megre(ans,ans,t[x]);return;}downdata(x);if(r<=t[x*2].r) Ask(x*2,l,r);else if(l>t[x*2].r) Ask(x*2+1,l,r);else Ask(x*2,l,t[x*2].r),Ask(x*2+1,t[x*2+1].l,r);megre(t[x],t[x*2],t[x*2+1]);}void Change(int x,int l,int r,int z){if(t[x].l==l&&t[x].r==r){t[x].w=1;t[x].lazy=t[x].rc=t[x].lc=z;return;}downdata(x);if(r<=t[x*2].r) Change(x*2,l,r,z);else if(l>t[x*2].r) Change(x*2+1,l,r,z);else Change(x*2,l,t[x*2].r,z),Change(x*2+1,t[x*2+1].l,r,z);megre(t[x],t[x*2],t[x*2+1]);}
}Tree;
void Reset()
{ans.w=ans.rc=0;}
void doing(int &x,int &y)
{if(!B){if(x>=t+1) x=x-t;else x=n-t+x;if(y>=t+1) y=y-t;else y=n-t+y;}else{if(x<=t+1) x=t-x+2;else x=t+n-x+2;if(y<=t+1) y=t-y+2;else y=t+n-y+2;swap(x,y);}
}
int main()
{scanf("%d%d",&n,&C);Tree.build(1,1,n);scanf("%d",&m);for(int i=1;i<=m;i++){char op[3];scanf("%s",op);if(op[0]=='C'){if(op[1]=='S'){int x,y;scanf("%d%d",&x,&y);if(x==y)x++,x--;doing(x,y);if(y>=x) Reset(),Tree.Ask(1,x,y);else {Tree_node a1,a2;Reset();Tree.Ask(1,x,n);a1=ans;Reset();Tree.Ask(1,1,y);a2=ans;if(B){swap(a1.lc,a1.rc);swap(a2.lc,a2.rc);swap(a1,a2);}Tree.megre(ans,a1,a2);}printf("%d\n",ans.w);}elseprintf("%d\n",max(Tree.t[1].w-(Tree.t[1].lc==Tree.t[1].rc),1));}else if(op[0]=='R'){int k;scanf("%d",&k);t=(t+k)%n;}else if(op[0]=='F') B^=1,t=n-t;else if(op[0]=='S'){int x,y;scanf("%d%d",&x,&y);doing(x,y);Reset();Tree.Ask(1,x,x);int a1=ans.lc;Reset();Tree.Ask(1,y,y);int a2=ans.lc;Tree.Change(1,x,x,a2);Tree.Change(1,y,y,a1);}else if(op[0]=='P'){int x,y,z;scanf("%d%d%d",&x,&y,&z);doing(x,y);if(y>=x) Tree.Change(1,x,y,z);else Tree.Change(1,x,n,z),Tree.Change(1,1,y,z);}}
}

P4130,jzoj1214-[NOI2007]项链工厂【线段树】相关推荐

  1. [线段树] Jzoj P1214 项链工厂

    Description T 公司是一家专门生产彩色珠子项链的公司,其生产的项链设计新颖.款式多样.价格适中,广受青年人的喜爱.最近T 公司打算推出一款项链自助生产系统,使用该系统顾客可以自行设计心目中 ...

  2. 【周末狂欢赛6】[AT1219]历史研究(回滚莫队),大魔法师(矩阵+线段树),单峰排列

    文章目录 T1:单峰排列 题目 题解 code T2:历史研究 题目 题解 code T3:大魔法师 题目 题解 code 我可能这辈子都更不出来狂欢赛5了,先咕咕 T1:单峰排列 题目 一个n的全排 ...

  3. bzoj 3838: [Pa2013]Raper (线段树)

    3838: [Pa2013]Raper Time Limit: 60 Sec  Memory Limit: 128 MB Submit: 53  Solved: 27 [Submit][Status] ...

  4. BIT与线段树专项练习

    线段树专项练习 这个草稿存在于我的CSDN良久,最近一场div2的E题出现了一次线段树相关,所以开始填坑. 以下关于加法.乘法和根号线段树来自之前久远的某一天. HH的项链 第二次做,20分钟切掉.但 ...

  5. 斜率优化之李超线段树

    三对于斜率优化,分为三种类型,一是斜率单调,第二种是是斜率不单调可以二分,第三种便是毫无规律可言的斜率情况,采用李超线段树可以在log范围内快速查询与修改,且能够胜任全部情况,代码与时间复杂度都很优秀 ...

  6. 二逼平衡树——树套树(线段树套Splay平衡树)

    题面 Bzoj3196 解析 线段树和Splay两棵树套在一起,常数直逼inf,但最终侥幸过了 思路还是比较简单, 在原数组维护一个下标线段树,再在每一个线段树节点,维护一个对应区间的权值Splay. ...

  7. 线段树——HDU - 1698

    题目含义 就是初始化一堆数为1 可以经过操作把一个区间的数都改变 并求这堆数的总大小 题目分析 有一个 #include<iostream> #include<stdio.h> ...

  8. BZOJ.1558.[JSOI2009]等差数列(线段树 差分)

    BZOJ 洛谷 首先可以把原序列\(A_i\)转化成差分序列\(B_i\)去做. 这样对于区间加一个等差数列\((l,r,a_0,d)\),就可以转化为\(B_{l-1}\)+=\(a_0\),\(B ...

  9. 【线段树分治 线性基】luoguP3733 [HAOI2017]八纵八横

    不知道为什么bzoj没有HAOI2017 题目描述 Anihc国有n个城市,这n个城市从1~n编号,1号城市为首都.城市间初始时有m条高速公路,每条高速公路都有一个非负整数的经济影响因子,每条高速公路 ...

最新文章

  1. SAP LSMW 物料主数据导入毛重净重放大1000倍问题之对策
  2. fedora利用vmlinuz和initrd制作linux启动u盘,Fedora 17的U盘安装方法
  3. sql动态拼接<if>标签嵌套<foreach>判空、if失效等问题
  4. ubuntu java classpath 设置_在Ubuntu中正确设置java classpath和java_home
  5. 计算机专业大学排名_U.S.News全美大学排名出炉:UCLA超越伯克利;计算机MIT排第一,斯坦福跌出前四...
  6. 6个技术问题及解决方案
  7. Python批量导入图片生成能治疗颈椎病的HTML5版课件
  8. Python(2.7.6) 迭代器
  9. 人工智能就是计算机科学的英文,AI(人工智能)的英文全称?AI指什么,包含什么?
  10. 新唐N76E003与ST公司STM8S003F3芯片对比 史上最全的没有之一
  11. 深度学习——反向传播(Backpropagation)
  12. 内网外网双通下的一种网络拓补方案
  13. Unable to set localhost. This prevents creation of a GUID. Cause was: cloud: cloud java.net.UnknownH
  14. NJCTF writeup
  15. mysqldatareader什么意思_MySqlDataReader
  16. USB-IF BC1.2充电协议解读
  17. Google BERT 中文应用之《红楼梦》中对话人物提取
  18. 错题日志(哈理工热身赛)
  19. 证据权重 (WOE) 与信息价值 (IV)
  20. 【追踪】两列动车在温州追尾事故现场

热门文章

  1. java float转换成long_在Java中如何将float转换为long或int数据类型?
  2. java密码学原型算法_java密码学原型算法实现——双线性对.pdf
  3. 计算机在学前教育和美术绘画中的应用,幼儿园美术教学活动中信息技术的应用...
  4. io流图解 java_详细讲解JAVA中的IO流
  5. 数据结构——基于 Dijsktra 算法的最短路径求解
  6. linux开发亿连手机互联,亿连手机互联车载版下载-亿连手机互联车机版v6.6.1 安卓版-腾牛安卓网...
  7. mysql下载了解压版怎么_教你安装Mysql(解压版/非安装包)图文教程
  8. AcWing 1015. 摘花生
  9. [蓝桥杯2016决赛]一步之遥-枚举
  10. python3.7和3.5_Ubuntu更新python3.5到python3.7