P4130 [NOI2007]项链工厂

间隙

大致题意

给一个串包含(n)个珠子的项链,其中第(i)个珠子的颜色是(c_i)

现在要求维护以下几个操作:

(n,m≤500000)

分析

细节巨多的一道线段树题

调了将近四个小时/kk

如果没有翻转操作,这就是个线段树裸题

不难发现,翻转操作只是把顺时针旋转变成了逆时针旋转

维护两个变量(r)(k),分别代表旋转的幅度和是否翻转,然后就可以通过计算轻松搞出查询区间了

亿点细节

  • 区间颜色全部相同时要特判

  • 旋转后区间要翻转

  • 注意题目中给的是一个环,因此要特判(l≤r)(l>r)的情况

  • 区间赋值相加tag,傻逼!

  • 交换操作用原数列数据,傻逼!

using namespace std;
const int MAXN = 500010;
#define lson node<<1
#define rson node<<1|1 
inline int read(){
	int X=0; bool flag=1; char ch=getchar();
	while(ch<'0'||ch>'9') {if(ch=='-') flag=0; ch=getchar();}
	while(ch>='0'&&ch<='9') {X=(X<<1)+(X<<3)+ch-'0'; ch=getchar();}
	if(flag) return X;
	return ~(X-1);
}
int n,m,a[MAXN];
int now;
int T[MAXN];
int cnt = 0;
bool is_rotate;
struct st{
	int l,r,val,tag;
}tree[MAXN<<2];
stack<st> s;
void pushdown(int node){
	if(!tree[node].tag) return;
	tree[lson].l = tree[lson].r = tree[rson].l = tree[rson].r = tree[node].tag;
	tree[lson].tag = tree[node].tag;
	tree[rson].tag = tree[node].tag;
	tree[lson].val = tree[rson].val = 1;
	tree[node].tag = 0;
}
void pushup(int node){
	tree[node].l = tree[lson].l;
	tree[node].r = tree[rson].r;
	if(tree[lson].r == tree[rson].l){
		tree[node].val = tree[lson].val+tree[rson].val -1;
	}
	else tree[node].val = tree[lson].val+tree[rson].val;
}
void build(int node,int l,int r){
	if(l==r){
		tree[node].l = tree[node].r = a[l];
		tree[node].val = 1;
		return;
	}
	int mid = (l+r)>>1;
	build(lson,l,mid);
	build(rson,mid+1,r);
	pushup(node);
}
int query(int node,int l,int r,int x,int y){
	if(x<=l&&y>=r){
		return tree[node].val;
	}
	pushdown(node);
	int mid = (l+r)>>1;
	if(x<=mid&&y>mid) return query(lson,l,mid,x,y)+query(rson,mid+1,r,x,y)-(tree[lson].r==tree[rson].l);
	if(x<=mid) return query(lson,l,mid,x,y);
	if(y>mid) return query(rson,mid+1,r,x,y);
	pushup(node);
}
st find(int node,int l,int r,int x,int y){
	if(x<=l&&y>=r){
		return tree[node];
	}
	pushdown(node);
	int mid = (l+r)>>1;
	if(x<=mid) return find(lson,l,mid,x,y);
	if(y>mid) return find(rson,mid+1,r,x,y);
	
}

/*int merge2(){
	int ans = 0;
	st last;
	while(!s.empty()){
		st a = s.top();
		s.pop();
		ans+=a.val;
		if(a.l==last.r) ans--;
		last = a;
		//cout<<"["<<a.l<<" "<<a.r<<"]"<<" "<<a.val<<" ";
	}
	return ans;
}*/
void modify(int node,int l,int r,int x,int y,int val){
	if(x<=l&&y>=r){
		tree[node].val = 1;
		tree[node].tag = val;
		tree[node].l = tree[node].r = val;
		return;
	}
	pushdown(node);
	int mid = (l+r)>>1;
	if(x<=mid) modify(lson,l,mid,x,y,val);
	if(y>mid) modify(rson,mid+1,r,x,y,val);
	pushup(node);
}

void calc(int &x,int &y){
	if(!is_rotate)
    {
        if(x>=now+1)x=x-now;
        else x=n-now+x;
        if(y>=now+1) y=y-now;
        else y=n-now+y;
    }else
    {
        if(x<=now+1)x=now-x+2;
        else x=now+n-x+2;
        if(y<=now+1) y=now-y+2;
        else y=now+n-y+2;
    }
} 
int main(){
	n = read(),m = read();
	for(int i=1;i<=n;i++) a[i] = read();
    build(1,1,n);
    int t;
    t = read();
    while(t--){
    	char opt[2];
    	cin>>opt;
    	if(opt[0]=='R'){
    		int k = read();
    		now = (now+k)%n;
		}
		else if(opt[0]=='F'){
			is_rotate = !is_rotate;
			now = (n-now)%n;
		}
		else if(opt[0]=='P'){
			int l = read(),r = read(),val = read();
			calc(l,r);
			if(is_rotate) swap(l,r);
			if(l<=r) modify(1,1,n,l,r,val);
			else modify(1,1,n,l,n,val),modify(1,1,n,1,r,val);
		}
		else if(opt[0]=='C'&&opt[1]!='S'){
			if(tree[1].l!=tree[1].r) cout<<tree[1].val<<endl;//T[++cnt] = tree[1].val;
			else cout<<max(1,tree[1].val - 1)<<endl;//T[++cnt] = tree[1].val-1;
		}
		else if(opt[0]=='S'){
			int l =read(),r = read();
			calc(l,r);
			st a = find(1,1,n,l,l);
			st b = find(1,1,n,r,r);
			modify(1,1,n,l,l,b.l);
			modify(1,1,n,r,r,a.l);

		}
		else{
			int l = read(),r = read();
			calc(l,r);
			if(is_rotate) swap(l,r);
			//cout<<"["<<l<<" "<<r<<"]"<<endl;
			if(l<=r) cout<<query(1,1,n,l,r)<<endl;
			else{
				cout<<max(1,query(1,1,n,l,n)+query(1,1,n,1,r)-(tree[1].l==tree[1].r))<<endl; 
			}
			 // T[++cnt] = merge();
		}
	}
	
}
原文地址:https://www.cnblogs.com/xcxc82/p/14013498.html