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. redis 的安装及常用的命令

    前言: redis是一个key-value的存储系统,value支持string.list.set.zset.hash五种类型,且支持数据的本地存储 一.安装redis 前提:linux下需要安装了m ...

  2. list & dictionary

    list不能直接进行对应,dictionary可以 list用[],dictionary用{}

  3. windows窗口过程函数名词解析

    windows窗口过程函数名词解析 LRESULT CALLBACK WndProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam) 1. LR ...

  4. poj 3253 Fence Repair (优先队列,哈弗曼)

    题目链接:http://poj.org/problem?id=3253 题意:给出n块木板的长度L1,L2...Ln,求在一块总长为这个木板和的大木板中如何切割出这n块木板花费最少,花费就是将木板切割 ...

  5. NOI模拟(3.6)Assignment

    Description 随机生成一个长度为m且每个元素都为1~n之间的整数的单调不下降序列~(即序列的(i>1)都不小于),(随机生成指每一种可能的序列都等概率被生成).请问这个序列的众数出现次 ...

  6. vue 子组件修改父组件变量问题

    昨天遇到一个这样的场景, 主页面引用了一个子页面,子页面有个Redio选择,2个选项. 默认的,会从父组件传递一个参数给子组件作为默认值,实现默认选中效果,以及用来做反选. 开始没什么问题,页面都摆上 ...

  7. expdp,impdp,include,exclude

    The examples below are based on:- the demo schema SCOTT that is created with script: $ORACLE_HOME/rd ...

  8. Redis 配置【十】

    参考:http://www.runoob.com/redis/redis-conf.html Redis 的配置文件位于 Redis 安装目录下,文件名为 redis.conf. 你可以通过 CONF ...

  9. BitMap算法 .net实现 用于去重并且排序,适用于大型权限管理 ,大数据去重排序

    BitMap利用byte特性 针对排序+去重  最佳实践: 100万条数据的排序+去重用时200毫秒左右 static void Main(string[] args) { ]; /*alias*/ ...

  10. base64加解密字符串

    import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOExceptio ...