zoukankan      html  css  js  c++  java
  • BZOJ_1493_[NOI2007]项链工厂_Splay

    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
    ",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
    ",max(ans1+ans2-(c1==c2),1));
    				}else {
    					printf("%d
    ",max(get_ans(x,y),1));
    				}
    			}else {
    				int c1=val[find(2)],cn=val[find(n+1)];
    				printf("%d
    ",max(get_ans(1,n)-(c1==cn),1));
    			}
    		}
    	}
    }
    
  • 相关阅读:
    目前服务器所需要的技能
    c++11 初始化列表 bind function 示例
    c++11 时间相关操作练习
    C++ Crypto++ RSA加密资料收集
    多线程查找大量数据加锁的速度降低
    c++沉思录 学习笔记 第六章 句柄(引用计数指针雏形?)
    c++沉思录 学习笔记 第五章 代理类
    boost asio 一个聊天的基本框架
    c++11 并发 条件变量 超时等待的代码练习
    centos 6.5 hadoop 2.3 初配置
  • 原文地址:https://www.cnblogs.com/suika/p/9108874.html
Copyright © 2011-2022 走看看