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

[NOI2007] 项链工厂

★★★   输入文件:necklace.in   输出文件:necklace.out   简单对比
时间限制:4 s  
内存限制:512 MB

【问题描述】

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

该项链自助生产系统包括硬件系统与软件系统,软件系统与用户进行交互并控制硬件系统,硬件系统接受软件系统的命令生产指定的项链。该系统的硬件系统已经完成,而软件系统尚未开发,T公司的人找到了正在参加全国信息学竞赛的你,你能帮助T公司编写一个软件模拟系统吗?

一条项链包含N个珠子,每个珠子的颜色是1, 2, …, c中的一种。项链被固定在一个平板上,平板的某个位置被标记位置1,按顺时针方向其他位置被记为2,3,…,N。

你将要编写的软件系统应支持如下命令:

命令 参数限制 内容
R k 0 意为Rotate k。将项链在平板上顺时针旋转k个位置, 即原来处于位置1的珠子将转至位置k+1,处于位置2的珠子将转至位置k+2,依次类推。
F   意为Flip。将平板沿着给定的对称轴翻转,原来处于位置1的珠子不动,位置2上的珠子与位置N上的珠子互换,位置3上的珠子与位置N-1上的珠子互换,依次类推。
S i j 1≤i , j≤N 意为Swap i , j。将位置i上的珠子与位置j上的珠子互换。
P i j x 1≤i , j≤N, x≤c 意为Paint i , j , x。将位置i沿顺时针方向到位置j的一段染为颜色x。
C   意为Count。查询当前的项链由多少个“部分”组成,我们称项链中颜色相同的一段为一个“部分”
CS i j 1≤i , j≤N 意为CountSegment i , j。查询从位置i沿顺时针方向到位置j的一段中有多少个部分组成。

【输入文件】

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

【输出文件】

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

【输入样例】

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

【输出样例】

4
1

【评分方法】

本题没有部分分,你的程序的输出只有和标准答案完全一致才能获得满分, 否则不得分。

【数据规模和约定】

  • 对于60%的数据,N ≤1 000,Q ≤1 000;
  • 对于100%的数据,N ≤500 000,Q ≤500 000,c ≤1 000。

  改了一上午终于AC!

  发现自己一直看错题了,Flip指令要以1为中轴,所以1不参与Flip!!!

  1 #include <iostream>
  2 #include <cstring>
  3 #include <cstdio>
  4 using namespace std;
  5 const int maxn=500010;
  6 int ch[maxn][2],fa[maxn],sz[maxn],flip[maxn],mark[maxn];
  7 int key[maxn],tot[maxn],L[maxn],R[maxn],rt;
  8 int n,Q,l,r,d,c;
  9 char op[10];
 10 void Push_up(int x){
 11     sz[x]=sz[ch[x][0]]+sz[ch[x][1]]+1;
 12     L[x]=ch[x][0]?L[ch[x][0]]:key[x];
 13     R[x]=ch[x][1]?R[ch[x][1]]:key[x];
 14     tot[x]=tot[ch[x][0]]+tot[ch[x][1]]+1;
 15     if(ch[x][0]&&R[ch[x][0]]==key[x])tot[x]-=1;
 16     if(ch[x][1]&&key[x]==L[ch[x][1]])tot[x]-=1;
 17 }
 18
 19 void Flip(int x){
 20     if(!x)return;
 21     swap(ch[x][0],ch[x][1]);
 22     swap(L[x],R[x]);
 23     flip[x]^=1;
 24 }
 25
 26 void Mark(int x,int d){
 27     if(!x)return;
 28     key[x]=L[x]=R[x]=d;
 29     tot[x]=1;mark[x]=d;
 30 }
 31
 32 void Push_down(int x){
 33     if(mark[x]!=-1){
 34         Mark(ch[x][0],mark[x]);
 35         Mark(ch[x][1],mark[x]);
 36         mark[x]=-1;
 37     }
 38     if(flip[x]){
 39         Flip(ch[x][0]);
 40         Flip(ch[x][1]);
 41         flip[x]=0;
 42     }
 43 }
 44
 45 void Rotate(int x){
 46     int y=fa[x],g=fa[y],c=ch[y][1]==x;
 47     ch[y][c]=ch[x][c^1];fa[ch[y][c]]=y;
 48     ch[x][c^1]=y;fa[y]=x;fa[x]=g;
 49     if(g)ch[g][ch[g][1]==y]=x;
 50     Push_up(y);
 51 }
 52
 53 void Splay(int x,int g=0){
 54     for(int y;(y=fa[x])!=g;Rotate(x))
 55         if(fa[y]!=g)
 56             Rotate((ch[fa[y]][1]==y)==(ch[y][1]==x)?y:x);
 57     Push_up(x);
 58     if(!g)rt=x;
 59 }
 60
 61 int Build(int x,int l,int r){
 62     if(l>r)return 0;
 63     int mid=(l+r)>>1;
 64     ch[mid][0]=Build(mid,l,mid-1);
 65     if(mid!=1&&mid!=n+2)
 66         scanf("%d",&key[mid]);
 67     ch[mid][1]=Build(mid,mid+1,r);
 68     sz[mid]=1;mark[mid]=-1;
 69     fa[mid]=x;Push_up(mid);
 70     return mid;
 71 }
 72
 73 int Get_ID(int k){
 74     int p=rt;
 75     while(true){
 76         Push_down(p);
 77         if(sz[ch[p][0]]+1==k)break;
 78         if(sz[ch[p][0]]+1<k)k-=sz[ch[p][0]]+1,p=ch[p][1];
 79         else p=ch[p][0];
 80     }
 81     return p;
 82 }
 83
 84 int main(){
 85 #ifndef ONLINE_JUDGE
 86     freopen("necklace.in","r",stdin);
 87     freopen("necklace.out","w",stdout);
 88 #endif
 89     scanf("%d%d",&n,&c);
 90     rt=Build(0,1,n+2);
 91     scanf("%d",&Q);
 92     while(Q--){
 93         scanf("%s",op);
 94         if(op[0]==‘R‘){
 95             scanf("%d",&d);d%=n;
 96             if(d==0)continue;
 97             Splay(Get_ID(n-d+1));
 98             Splay(Get_ID(n+2),rt);
 99             int tmp=ch[ch[rt][1]][0];
100             ch[ch[rt][1]][0]=0;
101             Splay(Get_ID(1));
102             Splay(Get_ID(2),rt);
103             ch[ch[rt][1]][0]=tmp;
104             fa[tmp]=ch[rt][1];
105         }
106         else if(op[0]==‘F‘){
107             Splay(Get_ID(2));
108             Splay(Get_ID(n+2),rt);
109             Flip(ch[ch[rt][1]][0]);
110         }
111         else if(op[0]==‘S‘){
112             scanf("%d%d",&l,&r);
113             if(l>r)swap(l,r);
114             if(l==r)continue;
115             Splay(Get_ID(l+1));
116             Splay(Get_ID(r+1),rt);
117             swap(key[rt],key[ch[rt][1]]);
118         }
119         else if(op[0]==‘P‘){
120             scanf("%d%d%d",&l,&r,&d);
121             if(l<=r){
122                 Splay(Get_ID(l));
123                 Splay(Get_ID(r+2),rt);
124                 Mark(ch[ch[rt][1]][0],d);
125             }
126             else{
127                 Splay(Get_ID(l));
128                 Splay(Get_ID(n+2),rt);
129                 Mark(ch[ch[rt][1]][0],d);
130                 Splay(Get_ID(1));
131                 Splay(Get_ID(r+2),rt);
132                 Mark(ch[ch[rt][1]][0],d);
133             }
134         }
135         else if(op[0]==‘C‘&&op[1]!=‘S‘){
136             Splay(Get_ID(1));
137             Splay(Get_ID(n+2),rt);
138             if(L[ch[ch[rt][1]][0]]==R[ch[ch[rt][1]][0]]&&tot[ch[ch[rt][1]][0]]>1)
139                 printf("%d\n",tot[ch[ch[rt][1]][0]]-1);
140             else
141                 printf("%d\n",tot[ch[ch[rt][1]][0]]);
142         }
143         else if(op[0]==‘C‘&&op[1]==‘S‘){
144             scanf("%d%d",&l,&r);
145             if(l<=r){
146                 Splay(Get_ID(l));
147                 Splay(Get_ID(r+2),rt);
148                 printf("%d\n",tot[ch[ch[rt][1]][0]]);
149             }
150             else{
151                 int ans=0;
152                 Splay(Get_ID(l));
153                 Splay(Get_ID(n+2),rt);
154                 ans+=tot[ch[ch[rt][1]][0]];
155                 Splay(Get_ID(1));
156                 Splay(Get_ID(r+2),rt);
157                 ans+=tot[ch[ch[rt][1]][0]];
158                 Splay(Get_ID(1));
159                 Splay(Get_ID(n+2),rt);
160                 if(L[ch[ch[rt][1]][0]]==R[ch[ch[rt][1]][0]])
161                     ans-=1;
162                 printf("%d\n",ans);
163             }
164         }
165     }
166     return 0;
167 }
时间: 2024-08-29 04:43:10

数据结构(Splay平衡树): [NOI2007] 项链工厂的相关文章

【BZOJ 1493】[NOI2007]项链工厂

1493: [NOI2007]项链工厂 Time Limit: 30 Sec  Memory Limit: 64 MB Submit: 992  Solved: 454 [Submit][Status] Description   Input 输入文件第一行包含两个整数N, c,分别表示项链包含的珠子数目以及颜色 数目.第二行包含N 个整数,x1, x2-, xn,表示从位置1 到位置N 的珠子的颜色, 1 ≤ xi ≤ c.第三行包含一个整数Q,表示命令数目.接下来的Q 行每行一条命令, 如上

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

1493: [NOI2007]项链工厂 Time Limit: 30 Sec  Memory Limit: 64 MBSubmit: 1256  Solved: 545[Submit][Status][Discuss] Description Input 输 入文件第一行包含两个整数N, c,分别表示项链包含的珠子数目以及颜色 数目.第二行包含N 个整数,x1, x2…, xn,表示从位置1 到位置N 的珠子的颜色, 1 ≤ xi ≤ c.第三行包含一个整数Q,表示命令数目.接下来的Q 行每行一

BZOJ1493 [NOI2007]项链工厂

未完待续... 1493: [NOI2007]项链工厂 Time Limit: 30 Sec  Memory Limit: 64 MBSubmit: 1320  Solved: 576[Submit][Status][Discuss] Description T公司是一家专门生产彩色珠子项链的公司,其生产的项链设计新颖.款式多样.价格适中,广受青年人的喜爱. 最近T公司打算推出一款项链自助生产系统,使用该系统顾客可以自行设计心目中的美丽项链.该项链自助生产系 统包括硬件系统与软件系统,软件系统与

NOI2007项链工厂——sbTreap代码

1 2 #include <iostream> 3 #include <cstdio> 4 #include <algorithm> 5 #include <cstring> 6 #include <cstdlib> 7 8 using namespace std; 9 struct node 10 { 11 int data; 12 int left; 13 int right; 14 int key; 15 int size; 16 bool

bzoj1493[NOI2007]项链工厂 线段树

1493: [NOI2007]项链工厂 Time Limit: 30 Sec  Memory Limit: 64 MBSubmit: 1712  Solved: 723[Submit][Status][Discuss] Description T公司是一家专门生产彩色珠子项链的公司,其生产的项链设计新颖.款式多样.价格适中,广受青年人的喜爱. 最近T公司打算推出一款项链自助生产系统,使用该系统顾客可以自行设计心目中的美丽项链.该项链自助生产系 统包括硬件系统与软件系统,软件系统与用户进行交互并控

数据结构(Splay平衡树):HDU 1890 Robotic Sort

Robotic Sort Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 3456    Accepted Submission(s): 1493 Problem Description Somewhere deep in the Czech Technical University buildings, there are labora

BZOJ 1493 NOI2007 项链工厂

题目大意:维护一个环,每个点有一个颜色,提供6种操作: 1.将这个环顺时针旋转k 2.沿点1所在直径翻转 3.将两个珠子互换 4.将一段区间染色 5.查询这个环上有多少颜色段 6.查询一段区间有多少颜色段 关于颜色段通用的处理方法是每个区间记录三个值,颜色段数.左端点颜色.右端点颜色,合并时颜色段数相加,如果左区间右端点和右区间左端点颜色相同则减一 然后用Splay维护区间即可 不过这题还是有一些小细节需要处理 首先null节点要保证不会被修改 然后更新的时候特判 如果一段区间颜色是0直接返回另

数据结构(Splay平衡树):COGS 339. [NOI2005] 维护数列

339. [NOI2005] 维护数列 ★★★★☆   输入文件:seq2005.in   输出文件:seq2005.out   简单对比 时间限制:3 s   内存限制:256 MB [问题描述] 请写一个程序,要求维护一个数列,支持以下 6 种操作:(请注意,格式栏 中的下划线‘ _ ’表示实际输入文件中的空格) 操作编号 输入文件中的格式 说明 1.  插入 INSERT_posi_tot_c1_c2_..._ctot 在当前数列的第 posi 个数字后插入 tot 个数字:c1, c2,

BZOJ1493 NOI2007 项链工厂 线段树模拟

提交地址:http://www.lydsy.com/JudgeOnline/problem.php?id=1493 题目大意:给一个数列,进行一系列操作.包括旋转,翻转,改变等操作,以及查询颜色段数. 题目分析:数列中元素的相对位置没有改变,因此不需要用splay去做,而是可以用线段树解决这类问题. 旋转操作直接改变变量rotate,翻转操作用异或即可.每次询问先利用rotate求出当前1号位是谁,这样可以根据翻转标记确定区间.如果区间跨越n,那么合并的时候要考虑左边一段的右端和右边一段的左端.