【uoj291】 ZJOI2017—樹狀數組

http://uoj.ac/problem/291 (題目連接)node

題意

  一個寫錯的樹狀數組有多大的機率與正常樹狀數組得出的答案同樣。ios

Solution

  能夠發現這個樹狀數組維護的是後綴和。數組

  因此二維線段樹維護二維數點$(l,r)$,表示左端點$l$與右端點$r$被修改次數相等的概率有多大。spa

  對於$l=1$的狀況,另外開一個普通的線段樹維護,操做不用重寫。blog

細節

  標記可持久化,否則好像會被hack數據卡TLE?get

代碼

// uoj291
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<cmath>
#define LL long long
#define inf (1ll<<29)
#define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout)
using namespace std;

const int maxn=100010,MOD=998244353;
int n,m,rt[maxn<<2],ans;
struct node {
	int son[2],p;
	int& operator [] (int x) {return son[x];}
}tr[maxn*400];

LL power(LL a,LL b) {
	LL res=1;
	while (b) {
		if (b&1) (res*=a)%=MOD;
		b>>=1;(a*=a)%=MOD;
	}
	return res;
}

namespace D2 {
	int sz;
	void modify(int &k,int l,int r,int s,int t,int p) {
		if (!k) k=++sz,tr[k].p=1;
		if (s<=l && r<=t) {
			tr[k].p=(1LL*tr[k].p*p%MOD+1LL*(1-tr[k].p+MOD)*(1-p+MOD)%MOD)%MOD;
			return;
		}
		int mid=(l+r)>>1;
		if (s<=mid) modify(tr[k][0],l,mid,s,t,p);
		if (t>mid) modify(tr[k][1],mid+1,r,s,t,p);
	}
	void query(int k,int l,int r,int p) {
		if (!k) return;
		ans=(1LL*ans*tr[k].p%MOD+1LL*(1-ans+MOD)*(1-tr[k].p+MOD)%MOD)%MOD;
		int mid=(l+r)>>1;
		if (p<=mid) query(tr[k][0],l,mid,p);
		else query(tr[k][1],mid+1,r,p);
	}
}

namespace D1 {
	void modify(int k,int l,int r,int s1,int t1,int s2,int t2,int p) {
		if (s1<=l && r<=t1) {
			D2::modify(rt[k],1,n,s2,t2,p);
			return;
		}
		int mid=(l+r)>>1;
		if (s1<=mid) modify(k<<1,l,mid,s1,t1,s2,t2,p);
		if (t1>mid) modify(k<<1|1,mid+1,r,s1,t1,s2,t2,p);
	}
	void query(int k,int l,int r,int s,int t) {
		D2::query(rt[k],1,n,t);
		if (l==r) return;
		int mid=(l+r)>>1;
		if (s<=mid) query(k<<1,l,mid,s,t);
		else query(k<<1|1,mid+1,r,s,t);
	}
}

int main() {
	scanf("%d%d",&n,&m);
	for (int op,l,r,i=1;i<=m;i++) {
		scanf("%d%d%d",&op,&l,&r);
		if (op==1) {
			int p=power(r-l+1,MOD-2);
			if (l!=r) D1::modify(1,1,n,l,r,l,r,(1-2*p%MOD+MOD)%MOD);
			if (l>1) {
				D1::modify(1,1,n,1,l-1,l,r,(1-p+MOD)%MOD);
				D2::modify(rt[0],1,n,1,l-1,0);
			}
			if (r<n) {
				D1::modify(1,1,n,l,r,r+1,n,(1-p+MOD)%MOD);
				D2::modify(rt[0],1,n,r+1,n,0);
			}
			D2::modify(rt[0],1,n,l,r,p);
		}
		if (op==2) {
			--l;ans=1;
			if (!l) D2::query(rt[0],1,n,r);
			else D1::query(1,1,n,l,r);
			printf("%d\n",ans);
		}
	}
    return 0;
}
相關文章
相關標籤/搜索