[bzoj1493]1493: [NOI2007]項鍊工廠 線段樹

1493: [NOI2007]項鍊工廠

Time Limit: 30 Sec  Memory Limit: 64 MB
[Submit][Status][Discuss]

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:



但注意此時項鍊上的位置編號仍然如圖1所示,於是翻轉的對稱軸不變。因而再執行一次“F”命令時,項鍊的顏色

如圖4所示。

2. 關於CountSegment命令CS命令表示查詢一個“線段”中有多少個“部分”。尤其注意當查詢的長度

等於 N 時,我們仍然將查詢部分作爲“線段”理解。例如在圖4所示的情況中,執行“CS 1 10”命令,查詢從位

置 1 開始到位置 10 結束的這個長度爲 10 的線段中有多少個“部分”,於是得到返回值 3 。與之形成對照的是

,若執行“C”命令,返回值則爲 2

Source

主要是處理座標比較噁心
線段樹部分灰常簡單
就是個裸線段樹還考處理座標
樣例數據操作還不全
關鍵是我第一次寫完時還把線段樹寫錯了,真是個智障
此題我又一次自帶大常數
#include <bits/stdc++.h>
using namespace std;
const int N = 5e5 + 5;
int delta=0,rev=0,n,c,a[N],q; char opt[5];
int flag[N<<2],sum[N<<2],lc[N<<2],rc[N<<2];
void update( int k ){
	lc[k] = lc[k<<1]; rc[k] = rc[k<<1|1];
	if( rc[k<<1] == lc[k<<1|1] ) sum[k] = sum[k<<1] + sum[k<<1|1] - 1;
	else sum[k] = sum[k<<1] + sum[k<<1|1];
}
void pushdown( int k ){
	if( flag[k] != -1 ){
		lc[k<<1] = lc[k<<1|1] = rc[k<<1] = rc[k<<1|1] = flag[k];
		flag[k<<1] = flag[k<<1|1] = flag[k];
		sum[k<<1] = sum[k<<1|1] = 1; flag[k] = -1;
	}
}
void build( int k, int l, int r ){
	flag[k] = -1;
	if( l == r ){
		lc[k] = rc[k] = a[l];
		sum[k] = 1;
		return ;
	}
	int mid = l + r >> 1;
	build( k<<1, l, mid );
	build( k<<1|1, mid+1, r );
	update( k );
}
void change( int k, int l, int r, int L, int R, int val ){
	if( L <= l && r <= R ){
		flag[k] = val; sum[k] = 1; lc[k] = rc[k] = val;
		return ;
	}
	int mid = l + r >> 1;
	pushdown( k );
	if( L <= mid ) change( k<<1, l, mid, L, R, val );
	if( R >  mid ) change( k<<1|1, mid+1, r, L, R, val );
	update( k );
}
int query( int k, int l, int r, int L, int R ){
	if( L <= l && r <= R ) return sum[k];
	int mid = l + r >> 1, ret = 0, lsr = 0, rsl = 0;
	pushdown( k );
	if( L <= mid ) ret += query( k<<1, l, mid, L, R ), lsr = rc[k<<1];
	if( R >  mid ) ret += query( k<<1|1, mid+1, r, L, R ), rsl = lc[k<<1|1];
	if( lsr && rsl && lsr == rsl ) ret--;
	update( k );
	return ret;
}
int query( int k, int l, int r, int x ){
	if( l == r ) return lc[k];
	int mid = l + r >> 1, res;
	pushdown( k );
	if( x <= mid ) res = query( k<<1, l, mid, x );
	else res = query( k<<1|1, mid+1, r, x );
	update(k);
	return res;
}
void change( int &l, int &r ){
	if( rev ){
		l = ( 2 * n + 2 - l - delta ) % n;
		r = ( 2 * n + 2 - r - delta ) % n;
		swap( l, r );
	}else{
		l = ( l + n - delta ) % n;
		r = ( r + n - delta ) % n;
	}
	l = l ? l : n; r = r ? r : n;
}
int main(){
	scanf( "%d%d", &n, &c );
	for( int i = 1; i <= n; i++ ) scanf( "%d", &a[i] );
	build( 1, 1, n ); scanf( "%d", &q );
	while( q-- ){
		scanf( "%s", opt ); int len = strlen(opt);
		if( opt[0] == 'R' ){
			int k;
			scanf( "%d", &k );
			if( rev ) delta = ( delta + n - k ) % n;
			else delta = ( delta + k ) % n;
		}
		if( opt[0] == 'F' ) rev ^= 1;
		if( opt[0] == 'S' ){
			int l, r, x, y;
			scanf( "%d%d", &l, &r );
			change( l, r );
			x = query( 1, 1, n, l );
			y = query( 1, 1, n, r );
			change( 1, 1, n, l, l, y );
			change( 1, 1, n, r, r, x );
		}
		if( opt[0] == 'P' ){
			int l, r, x;
			scanf( "%d%d%d", &l, &r, &x );
			change( l, r );
			if( l <= r ) change( 1, 1, n, l, r, x );
			else change( 1, 1, n, 1, r, x ), change( 1, 1, n, l, n, x );
		}
		if( opt[0] == 'C' && len == 1 ){
			int ret = query( 1, 1, n, 1, n );
//			printf( "%d %d\n", query( 1, 1, n, 1 ), query( 1, 1, n, n ) );
			if( query( 1, 1, n, 1 ) == query( 1, 1, n, n ) && ret != 1 ) ret--;
			printf( "%d\n", ret );
		}
		if( len == 2 ){
			int l, r;
			scanf( "%d%d", &l, &r );
			change( l, r );
			if( l <= r ){
				if( l == 1 && r == n ){
					int ret = query( 1, 1, n, 1, n );
					if( query( 1, 1, n, 1 ) == query( 1, 1, n, n ) && ret != 1 ) ret--;
					printf( "%d\n", ret );
				}else{
					printf( "%d\n", query( 1, 1, n, l, r ) );
				}
			}else{
				int ret = query( 1, 1, n, 1, r ) + query( 1, 1, n, l, n );
				if( query( 1, 1, n, 1 ) == query( 1, 1, n, n ) ) ret--;
				printf( "%d\n", ret );
			}
		}
	}
	return 0;
}/*
5 3
1 2 3 2 1
5
C
F
R 2
P 5 5 2
CS 4 1
*/


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章