BZOJ_1493_[NOI2007]项链工厂_Splay

Description

T公司是一家专门生产彩色珠子项链的公司,其生产的项链设计新颖、款式多样、价格适中,广受青年人的喜爱。
最近T公司打算推出一款项链自助生产系统,使用该系统顾客可以自行设计心目中的美丽项链。该项链自助生产系
统包括硬件系统与软件系统,软件系统与用户进行交互并控制硬件系统,硬件系统接受软件系统的命令生产指定的
项链。该系统的硬件系统已经完成,而软件系统尚未开发,T公司的人找到了正在参加全国信息学竞赛的你,你能
帮助T公司编写一个软件模拟系统吗?一条项链包含 N 个珠子,每个珠子的颜色是 1,2,…,c 中的一种。项链
被固定在一个平板上,平板的某个位置被标记位置 1 ,按顺时针方向其他位置被记为 2,3,…,N。
你将要编写的软件系统应支持如下命令:

Input

输入文件第一行包含两个整数 N,c ,分别表示项链包含的珠子数目以及颜色数目。
第二行包含 N 个整数,x1,x2,…,xn ,表示从位置 1 到位置 N 的珠子的颜色,1≤xi≤c 。
第三行包含一个整数 Q ,表示命令数目。接下来的 Q 行每行一条命令,如上文所述。N≤500000 ,Q≤500000,c≤1000 

Output

对于每一个 C 和 CS 命令,应输出一个整数代表相应的答案。

Sample Input

5 3
1 2 3 2 1
4
C
R 2
P 5 5 2
CS 4 1

Sample Output

4
1

HINT

注意旋转命令旋转“珠子”但不改变“位置”的编号,而反转命令始终以位置 1 为对称轴。例如当 N=10 时,项
链上的位置编号如图1:

线段树处理翻转标记不太会,直接上splay模拟。
每个节点额外维护左端的颜色,右端的颜色,区间的颜色段数。
R操作可以对整个序列进行3次区间翻转。
F操作对[2,n]执行区间翻转。
S操作两次单点修改。
P操作区间赋值。
C操作和CS操作直接查询区间再把重复的减掉即可。
注意0号结点不能拿来更新别的节点的值。
 
代码:
#include <cstdio>
#include <string.h>
#include <algorithm>
using namespace std;
#define RR register
int check[500];
void init() {
check['R']=check['F']=check['S']=check['P']=check['C']=1;
}
inline char nc() {
static char buf[100000],*p1,*p2;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline int rd() {
RR int x=0; RR char s=nc();
while(s<'0'||s>'9') s=nc();
while(s>='0'&&s<='9') x=(x<<3)+(x<<1)+s-'0',s=nc();
return x;
}
inline char rc() {
char s=nc();
while(!check[s]) s=nc();
return s;
}
#define N 500050
#define ls ch[p][0]
#define rs ch[p][1]
#define get(x) (ch[f[x]][1]==x)
int f[N],ch[N][2],val[N],cover[N],la[N],ra[N],as[N],rt,siz[N],rev[N],n,a[N];
void pushup(int p) {
if(!p) return ;
siz[p]=1;
if(ls) siz[p]+=siz[ls];
if(rs) siz[p]+=siz[rs];
la[p]=ra[p]=val[p];
if(ls) la[p]=la[ls];
if(rs) ra[p]=ra[rs];
as[p]=as[ls]+as[rs]+1;
if(ls&&val[p]==ra[ls]) as[p]--;
if(rs&&val[p]==la[rs]) as[p]--;
}
void pushdown(int p) {
if(!p) return ;
if(rev[p]) {
swap(ch[ls][0],ch[ls][1]); swap(ch[rs][0],ch[rs][1]);
swap(la[ls],ra[ls]); swap(la[rs],ra[rs]);
rev[ls]^=1; rev[rs]^=1; rev[p]=0;
}
if(cover[p]) {
int d=cover[p];
if(ls) la[ls]=ra[ls]=val[ls]=d,as[ls]=1,cover[ls]=d;
if(rs) la[rs]=ra[rs]=val[rs]=d,as[rs]=1,cover[rs]=d;
cover[p]=0;
}
}
void rotate(int x) {
int y=f[x],z=f[y],k=get(x);
ch[y][k]=ch[x][!k]; f[ch[y][k]]=y;
ch[x][!k]=y; f[y]=x; f[x]=z;
if(z) ch[z][ch[z][1]==y]=x;
pushup(y); pushup(x);
if(y==rt) rt=x;
}
void splay(int x,int y) {
for(int d;(d=f[x])!=y;rotate(x)) if(f[d]!=y) rotate(get(x)==get(d)?d:x);
}
int find(int x) {
int p=rt;
while(1) {
pushdown(p);
if(siz[ls]>=x) p=ls;
else {
x-=siz[ls]+1;
if(!x) return p;
p=rs;
}
}
}
void reverse(int x,int p) {
x=find(x); p=find(p+2);
splay(x,0); splay(p,rt);
rev[ls]^=1; swap(ch[ls][0],ch[ls][1]); swap(la[ls],ra[ls]);
if(ls) la[p]=ra[ls]; pushup(p); pushup(x);
}
void print() {
int i,p;
for(i=1;i<=n+2;i++) {
p=find(i);
printf("i=%d,p=%d,val[p]=%d,siz[p]=%d,f[p]=%d\n",i,p,val[p],siz[p],f[p]);
}
}
void build(int fa,int l,int r) {
if(l>r) return ;
int mid=(l+r)>>1;
val[mid]=a[mid-1];
siz[mid]=1;f[mid]=fa;
ch[fa][mid>fa]=mid;
build(mid,l,mid-1); build(mid,mid+1,r);
pushup(mid);
}
int get_ans(int x,int p) {
x=find(x); p=find(p+2);
splay(x,0); splay(p,rt);
return as[ls]?as[ls]:1;
}
void cover_col(int x,int y,int c) {
x=find(x); y=find(y+2); splay(x,0); splay(y,rt); int s=ch[y][0]; //print(); puts("FUCK");
cover[s]=c; val[s]=la[s]=ra[s]=c; as[s]=1; pushup(y); pushup(x);
}
void swapp(int x,int y) {
if(x==y) return ;
int cx=val[find(x+1)],cy=val[find(y+1)];
cover_col(x,x,cy); cover_col(y,y,cx);
}
int main() {
init();
int T;
n=rd(); T=rd();
int i,k,x,y;
for(i=1;i<=n;i++) a[i]=rd();
build(0,1,n+2); rt=(n+3)>>1;
char opt[10];
//print();
T=rd();
while(T--) {
opt[0]=rc();
if(opt[0]=='R') {
k=rd();
reverse(1,n); reverse(1,k); reverse(k+1,n); //print();
}else if(opt[0]=='F') {
reverse(2,n);
//print();
}else if(opt[0]=='S') {
x=rd(); y=rd();
swapp(x,y);
}else if(opt[0]=='P') {
x=rd(); y=rd(); k=rd();
if(x<=y) {
cover_col(x,y,k);
}else {
cover_col(x,n,k); cover_col(1,y,k);
}
//print();
}else if(opt[0]=='C') {
if(nc()=='S') {
x=rd(); y=rd();
if(x>y) {
int c1=val[find(2)],c2=val[find(n+1)];
int ans1=get_ans(x,n),ans2=get_ans(1,y);
printf("%d\n",max(ans1+ans2-(c1==c2),1));
}else {
printf("%d\n",max(get_ans(x,y),1));
}
}else {
int c1=val[find(2)],cn=val[find(n+1)];
printf("%d\n",max(get_ans(1,n)-(c1==cn),1));
}
}
}
}

BZOJ_1493_[NOI2007]项链工厂_Splay的更多相关文章

  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. 1493: [NOI2007]项链工厂

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

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

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

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

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

  8. NOI2007 项链工厂

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

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

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

随机推荐

  1. 零基础入门学习Python(7)--了不起的分支和循环1

    前言 我们今天的主题,是了不起的分支和循环,为什么不说c语言,Python了不起,而对分支和循环这两个知识点那么崇拜呢? 我们之前的几节课里也接触到了分支和循环,大家思考一下,如果我们的程序没有分支和 ...

  2. C#上位机开发(三)—— 构建SerialAssistant雏形

    上一篇简单介绍了C#的一些基本知识,并成功的Hello,World,那么从这篇开始,我们来自己动手写一个串口助手: 1.构思功能 串口助手在单片机开发中经常被用来调试,最基本的功能就是接收功能和发送功 ...

  3. matplotlib的使用--折线图--入门

    目录 matplotlib应用介绍 一天天气变化图 两小时随机温度图 中文显示问题 个人交往统计图 多人交往统计图 总结 介绍: 举个例子(一天天气变化图): 假设一天中每隔两个小时(range(2, ...

  4. 解方程(codevs 3732)

    题目描述 已知多项式方程: a0+a1x+a2x^2+..+anx^n=0 求这个方程在[1, m ] 内的整数解(n 和m 均为正整数) 输入输出格式 输入格式: 输入文件名为equation .i ...

  5. oracle将查询到的数据插入到数据库的表中

    一.Oracle数据库中,把一张表的查询结果直接生成并导入一张新表中.   例如:现有只有A表,查询A表,并且把结果导入B表中.使用如下SQL语句:   create table b as selec ...

  6. 莫比乌斯反演套路三、四--BZOJ2154: Crash的数字表格 && BZOJ2693: jzptab

    t<=1e4个询问每次问n,m<=1e7,$\sum_{1\leqslant x \leqslant n,1 \leqslant y\leqslant m}lcm(x,y)$. 首先题目要 ...

  7. 「CodePlus 2017 11 月赛」大吉大利,晚上吃鸡!

    n<=50000,m<=50000的图,给s和t,问有多少点对$(a,b)$满足 嗯. 不会. 首先最短路DAG造出来,然后两个条件转述一下:条件一,$N_a$表示从s到t经过a的路径,$ ...

  8. PKCS填充方式

    1)RSA_PKCS1_PADDING 填充模式,最常用的模式要求: 输入 必须 比 RSA 钥模长(modulus) 短至少11个字节, 也就是 RSA_size(rsa) – 11.如果输入的明文 ...

  9. UVA 10006_Carmichael number

    题意: N 为合数,对于任意一个在(1,N)之间的数满足 anmodn=a,则称N为Carmichael number,对于给定的N,判断是否为Carmichael number. 分析: 素数区间筛 ...

  10. SQL SERVER示例:修改自定义数据类型精度

    /*--修改自定义数据类型精度的示例      自定义数据类型一旦被引用,就不能再修改和删除,如果要修改数据的精度,就非常麻烦,下面的示例演示了如何修改      假设要修改的自定义变量名为aa -- ...