概率+树套树——UOJ#291/Luogu3688 [ZJOI2017]树状数组

来源:互联网 发布:linux创造普通用户 编辑:程序博客网 时间:2024/05/29 15:52

题面:Luogu3688 UOJ#291
我考场上这题打都没打QAQ,出来说这题是Day1最水的一道。。。
题目的大意嘛。。。就是这张图啦(Ps:orz SW_Wind)

(注意到可怜手上拿着的倒着的“树状数组”了吗


接下来开始了无限的懵逼。。。
过了N多个月,看了N多个题解之后,我终于懵逼地在luogu上卡着AC了
然而UOJ还是被卡常90分QAQ
首先要知道的是可怜写的sb“树状数组”求的是后缀和
于是对于某个区间[l,r],这个“树状数组”询问到的是[l1,r1]
唯一的区别就在于两个节点:l1r
还有因为在模2域下,所以我们只要关心两个节点同时被修改奇数次或者偶数次的概率就行了
所以我们把这两个点看成二元组,然后构建一棵树套树,外层左端点,内层右端点
修改操作的时候有几种情况:
1. 查询左端点在修改区间外,右端点在内,右端点的修改概率为1yx+1
2. 查询右端点在修改区间外,左端点在内,左端点的修改概率也是1yx+1
3. 查询两端点都在区间内,修改概率为2yx+1
4. 都不在,不用考虑(就是没有)

还有要特判l=1的情况,这种情况可怜的代码也有特判,因此只要关心右端点的情况就好了,修改同上

最后,我的程序是乱打的,然后莫名其妙在洛谷上AC了。。。

#include <cstdio>#include <algorithm>#include <cmath>#include <cstring>#include <iostream>#include <ctime>#include <map>#include <queue>#include <cstdlib>#include <string>#include <climits>#include <set>#include <vector>using namespace std;typedef long long ll;const ll MOD=998244353;ll ans=0;int root[400010],ls[40000010],rs[40000010],t[40000010],cnt=0,n,m;inline ll mi(ll a,ll b){    ll x=1,y=a;while(b){if(b&1)x=x*y%MOD;y=y*y%MOD;b>>=1;}return x;}inline ll cal(ll x,ll y){return (x+y-x*y*2%MOD+MOD)%MOD;}//合并概率inline void xg(int l,int r,int i,int j,int v,int& nod){//内层区间修改    if(!nod)nod=++cnt,t[nod]=0;    if(l>=i&&r<=j){t[nod]=cal(t[nod],v);return;}    int mid=l+r>>1;    if(i<=mid)xg(l,mid,i,j,v,ls[nod]);    if(j>mid)xg(mid+1,r,i,j,v,rs[nod]);}inline void Xg(int l,int r,int i1,int j1,int i2,int j2,int v,int nod){//外层区间修改    if(l>=i1&&r<=j1){xg(0,n,i2,j2,v,root[nod]);return;}    int mid=l+r>>1;    if(i1<=mid)Xg(l,mid,i1,j1,i2,j2,v,nod*2);    if(j1>mid)Xg(mid+1,r,i1,j1,i2,j2,v,nod*2+1);}inline void ssum(int l,int r,int i,int nod){//内层查询    if(!nod)return;    ans=cal(ans,t[nod]);if(l==r)return;//一直加的原因是区间修改的时候没有下传,和标记永久化有点像。。。    int mid=l+r>>1;    if(i<=mid)ssum(l,mid,i,ls[nod]);else ssum(mid+1,r,i,rs[nod]);}inline void Ssum(int l,int r,int i,int j,int nod){//外层查询    ssum(0,n,j,root[nod]);//同上    if(l==r)return;    int mid=l+r>>1;    if(i<=mid)Ssum(l,mid,i,j,nod*2);else Ssum(mid+1,r,i,j,nod*2+1);}int main(){    ios::sync_with_stdio(false);    cin>>n>>m;    while(m--){        int p,x,y;cin>>p>>x>>y;        if(p==1){            ll k=mi(y-x+1,MOD-2);            if(x>1)Xg(0,n,1,x-1,x,y,k,1);            if(y<n)Xg(0,n,x,y,y+1,n,k,1);            Xg(0,n,x,y,x,y,k*2ll%MOD,1);//对应的3种情况            Xg(0,n,0,0,0,x-1,1,1);            if(y<n)Xg(0,n,0,0,y+1,n,1,1);            Xg(0,n,0,0,x,y,k*(ll)(y-x)%MOD,1);//特判1        }else{            ans=1;Ssum(0,n,x-1,y,1);            cout<<ans<<endl;        }    }    return 0;}
原创粉丝点击