线段树WA10pts求调玄关
查看原帖
线段树WA10pts求调玄关
670978
Arc0_FishyFool楼主2025/7/22 21:38
#include <bits/stdc++.h>
using namespace std;
int coltag[1919810<<2],a[1919810],n,c,len[1919810<<2],q,hd=1,dir=1;
struct SegTree{
	int prt,lcol,rcol;
	SegTree(int prt=0,int lcol=0,int rcol=0):
	prt(prt),lcol(lcol),rcol(rcol){}
}t[1919810<<2];
SegTree pushup(SegTree lson,SegTree rson){
	return SegTree(((lson.rcol==rson.lcol&&lson.rcol)?lson.prt+rson.prt-1:lson.prt+rson.prt),lson.lcol,rson.rcol);
}
inline void tag(int x,int col){
	coltag[x]=col;
	t[x]=SegTree(1,col,col);
}
void pushdown(int x){
	if(coltag[x]){
		tag(x<<1,coltag[x]);
		tag(x<<1|1,coltag[x]);
		coltag[x]=0;
	}
}
void build(int x,int l,int r){
	len[x]=r-l+1;
	if(l==r){
		t[x]=SegTree(1,a[l],a[l]);
		return;
	}
	int mid=(l+r)>>1;
	build(x<<1,l,mid);
	build(x<<1|1,mid+1,r);
	t[x]=pushup(t[x<<1],t[x<<1|1]);
}
int findcol(int x,int l,int r,int pos){
	if(l==r&&l==pos) return t[x].lcol;
	pushdown(x);
	int mid=(l+r)>>1;
	if(mid>=pos) return findcol(x<<1,l,mid,pos);
	else return findcol(x<<1|1,mid+1,r,pos);
}
void flatten(int x,int l,int r,int L,int R,int col){
	if(L<=l&&r<=R){
		tag(x,col);
		return;
	}
	pushdown(x);
	int mid=(l+r)>>1;
	if(L<=mid) flatten(x<<1,l,mid,L,R,col);
	if(R>mid) flatten(x<<1|1,mid+1,r,L,R,col);
	t[x]=pushup(t[x<<1],t[x<<1|1]);
}
SegTree query(int x,int l,int r,int L,int R){
	if(L<=l&&r<=R){
		return t[x];
	}
	pushdown(x);
	SegTree r1,r2,res;
	r1=r2=SegTree();
	int mid=(l+r)>>1;
	if(L<=mid) r1=query(x<<1,l,mid,L,R);
	if(R>mid) r2=query(x<<1|1,mid+1,r,L,R);
	res=pushup(r1,r2);
	//puts("-------------");
	//printf("|%d_%d_%d\n",r1.prt,r1.lcol,r1.rcol);
	//printf("|%d_%d_%d\n",r2.prt,r2.lcol,r2.rcol);
//	printf("|%d_%d_%d\n",res.prt,res.lcol,res.rcol);
	return res;
}
int main(){
	scanf("%d%d",&n,&c);
	for(int i=1;i<=n;++i){
		scanf("%d",a+i);
		a[i+n]=a[i];
	}
	int N=2*n;
	build(1,1,N);
	scanf("%d",&q);
	while(q--){
		string opt;
		int i,j,x;
		cin>>opt;
		if(opt[0]=='R'){
			scanf("%d",&i);
			hd=((hd-1-dir*i)%n+n)%n+1;
			//printf("hd=%d\n",hd);
		}
		else if(opt[0]=='F'){
			dir=-dir;
			//printf("dir=%d\n",dir);
		}
		else if(opt=="C"){
			SegTree ans=query(1,1,N,1,N);
			printf("%d\n",ans.prt/2);
		}
		else{
			bool flag=false;
			int _i,_j;
			scanf("%d%d",&i,&j);
			if(dir<0) swap(j,i);
			i=((hd-1+dir*(i-1))%n+n)%n+1;
			j=((hd-1+dir*(j-1))%n+n)%n+1;
			_i=i+n;
			_j=j+n;
			if(i>j) flag=true;
			if(opt[0]=='S'){
				int coli=findcol(1,1,N,i),colj=findcol(1,1,N,j);
				flatten(1,1,N,i,i,colj);
				flatten(1,1,N,_i,_i,colj);
				flatten(1,1,N,j,j,coli);
				flatten(1,1,N,_j,_j,coli);
			}
			else if(opt[0]=='P'){
				scanf("%d",&x);
				if(flag){
					flatten(1,1,N,i,_j,x);
					flatten(1,1,N,_j,_i,x);
					flatten(1,1,N,_i,N,x);
					flatten(1,1,N,1,j,x);
				}
				else{
					flatten(1,1,N,i,j,x);
					flatten(1,1,N,_i,_j,x);
				}
			}
			else{
				SegTree ans;
				if(flag){
					ans=query(1,1,N,i,_j);
				}
				else{
					ans=query(1,1,N,i,j);
				}
				printf("%d\n",ans.prt);
			}
		}
	}
	return 0;
}

思路:
用2n大小数组存环,dir和hd描述顶点和方向(是否翻转),线段树写法参考P2572第一篇题解。这2n大小数组的部分数/2即环的部分数。每次修改都会同步修改2n数组中与i、j表示相同位置的点_i、_j,根据dir以及i、j大小关系决定修改哪些区间。

2025/7/22 21:38
加载中...