BZOJ4785: [Zjoi2017]树状数组

错的bit相当于查后缀和,所以就是求$l-1$和$r$相等的概率,转成二维限制,分类讨论一下就好了。

注意特判$l=1$。

注意没有可减性,因为存在零元$\frac12$,若记录零元个数就具备了可减性。

写二维线段树的话注意空间。

#include<cstdio>
#define I (J+1)
#define J (i+j>>1)
#define P (k<<1)
#define S (P^1)
typedef unsigned long long ll;
const int p=998244353;
int cal(ll a,ll b){
	return(a*(1+(p-b)*2)+b)%p;
}
const int N=1e5;
struct node{
	int i,j,a,b;
}e[N*300];
int l;
void ins(int a,int b,int x,int i,int j,int&k){
	if(!k)k=++l;
	e[k].a=cal(e[k].a,a);
	e[k].b=cal(e[k].b,b);
	if(i!=j)
		x<I?ins(a,b,x,i,J,e[k].i):ins(a,b,x,I,j,e[k].j);
}
int ask(int node::*p,int x1,int x2,int i,int j,int k){
	return!k?0:x1==i&&j==x2?e[k].*p:x2<I?ask(p,x1,x2,i,J,e[k].i):x1>J?ask(p,x1,x2,I,j,e[k].j):cal(ask(p,x1,J,i,J,e[k].i),ask(p,I,x2,I,j,e[k].j));
}
int n,r[N*4];
void ins(int a,int b,int x,int y,int i,int j,int k){
	ins(a,b,x,1,n,r[k]);
	if(i!=j)
		y<I?ins(a,b,x,y,i,J,P):ins(a,b,x,y,I,j,S);
}
void ins(int z,int x,int y){
	ins(z,z*2%p,x,y,1,n,1);
}
int ask(int node::*p,int x1,int x2,int y1,int y2,int i,int j,int k){
	return y1==i&&j==y2?ask(p,x1,x2,1,n,r[k]):y2<I?ask(p,x1,x2,y1,y2,i,J,P):y1>J?ask(p,x1,x2,y1,y2,I,j,S):cal(ask(p,x1,x2,y1,J,i,J,P),ask(p,x1,x2,I,y2,I,j,S));
}
int ask(int node::*p,int x1,int x2,int y1,int y2){
	return ask(p,x1,x2,y1,y2,1,n,1);
}
int inv(ll a){
	ll s=1;
	for(int n=p-2;n;n>>=1){
		if(n&1)s=s*a%p;
		a=a*a%p;
	}
	return s;
}
int main(){
	int m,o,u,v;
	scanf("%d%d",&n,&m);
	int w=1;
	while(m--){
		scanf("%d%d%d",&o,&u,&v);
		if(o==1){
			w^=1;
			ins(inv(v-u+1),u,v);
		}else{
			if(--u)
				printf("%d\n",cal(cal(cal(ask(&node::b,1,u,v,n),ask(&node::a,1,u,u,v-1)),ask(&node::a,u+1,v,v,n)),1));
			else
				printf("%d\n",cal(ask(&node::a,1,v,v,n),w));
		}
	}
}
posted @ 2017-04-01 03:43  f321dd  阅读(410)  评论(0编辑  收藏  举报