码迷,mamicode.com
首页 > 其他好文 > 详细

bzoj1858: [Scoi2010]序列操作 线段树

时间:2016-05-15 21:28:40      阅读:215      评论:0      收藏:0      [点我收藏+]

标签:

线段树,维护七个值两个标记。

用结构体快了一倍……

#include<bits/stdc++.h>
#define N (1<<18)
#define M (l+r>>1)
#define P (k<<1)
#define S (k<<1|1)
#define K l,r,k
#define L l,M,P
#define R M+1,r,S
#define Z int l=0,int r=n-1,int k=1
using namespace std;
int n;
static struct{
	int same,flip;
	int sum,u[2],v[2],a[2];
}a[N];
template<int d>
void make_same(Z){
	a[k].flip=0;
	a[k].sum=(a[k].same=d)*(r-l+1);
	 a[k].u[d^1]=a[k].v[d^1]
	=a[k].a[d^1]=0;
	 a[k].u[ d ]=a[k].v[ d ]
	=a[k].a[ d ]=r-l+1;
}
void make_flip(int,int,int);
void (*operate[3])(int,int,int)={
	make_same<0>,
	make_same<1>,
	make_flip
};
void make_flip(Z){
	if(~a[k].same)
		operate[a[k].same^1](K);
	else{
		a[k].flip^=1;
		a[k].sum=r-l+1-a[k].sum;
		swap(a[k].u[0],a[k].u[1]);
		swap(a[k].v[0],a[k].v[1]);
		swap(a[k].a[0],a[k].a[1]);
	}
}
void push_down(Z){
	if(~a[k].same){
		operate[a[k].same](L);
		operate[a[k].same](R);
		a[k].same=-1;
	}
	if(a[k].flip){
		operate[2](L);
		operate[2](R);
		a[k].flip=0;
	}
}
void update(Z){
	a[k].sum=a[P].sum+a[S].sum;
	for(int i=0;i!=2;++i){
		a[k].u[i]=a[P].u[i]
		+a[S].u[i]*(a[P].u[i]==M-l+1);
		a[k].v[i]=a[S].v[i]
		+a[P].v[i]*(a[S].v[i]==r-M);
		a[k].a[i]=max(max(
		a[P].a[i],a[S].a[i]),
		a[P].v[i]+a[S].u[i]);
	}
}
template<int d>
void A(int s,int t,Z){
	if(s==l&&t==r)
		operate[d](K);
	else{
		push_down(K);
		if(t<=M)
			A<d>(s,t,L);
		else if(s>M)
			A<d>(s,t,R);
		else{
			A<d>(s,M,L);
			A<d>(M+1,t,R);
		}
		update(K);
	}
}
int Q1(int s,int t,Z){
	if(s==l&&t==r)
		return a[k].sum;
	push_down(K);
	return t<=M?Q1(s,t,L)
	:s>M?Q1(s,t,R)
	:Q1(s,M,L)+Q1(M+1,t,R);
}
int Q2(int s,int t,Z){
	if(s==l&&t==r)
		return a[k].a[1];
	push_down(K);
	return t<=M?Q2(s,t,L)
	:s>M?Q2(s,t,R)
	:max(max(Q2(s,M,L),
	Q2(M+1,t,R)),
	 min(a[P].v[1],M-s+1)
	+min(a[S].u[1],t-M));
}
void build(Z){
	if(l==r){
		scanf("%d",&a[k].sum);
		operate[a[k].sum](K);
	}else{
		build(L);
		build(R);
		update(K);
		a[k].same=-1;
	}
}
int main(){
	int m;
	scanf("%d%d",&n,&m);
	build();
	while(m--){
		int op,a,b;
		scanf("%d%d%d",&op,&a,&b);
		if(op==0)
			A<0>(a,b);
		if(op==1)
			A<1>(a,b);
		if(op==2)
			A<2>(a,b);
		if(op==3)
			printf("%d\n",Q1(a,b));
		if(op==4)
			printf("%d\n",Q2(a,b));
	}
}

  

bzoj1858: [Scoi2010]序列操作 线段树

标签:

原文地址:http://www.cnblogs.com/f321dd/p/5495960.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!