loj#2251. 「ZJOI2017」樹狀數組(二維數點,樹套樹維護概率)

先放代碼,日後更。(*2)

===========================2018.3.21UPD===========================
題面在這裏

做法

容易發現只要將query的l1,r 改成r+1,l 就是正確的了。所以最後答案之和l1,r 這兩個點的奇偶性是否相同有關。問題轉化爲維護兩個位置的奇偶性相同的概率,二維數點,可以用樹套樹解決。注意l=1 的情況需要注意一下。

代碼

爲什麼我的代碼跑得那麼慢!!
人傻自帶大常數qwq。

/*
*   轉化題意;
*   二維數點;
*   分類討論;
*   概率論;
*/
#include<bits/stdc++.h>
#define rep(i,x,y) for (int i=(x); i<=(y); i++)
#define N 100010
#define M 40000010
#define ll long long
#define mod 998244353
#define lc (o<<1)
#define rc (o<<1|1)
using namespace std;
ll read(){
    char ch=getchar(); ll x=0; int op=1;
    for (; !isdigit(ch); ch=getchar()) if (ch=='-') op=-1;
    for (; isdigit(ch); ch=getchar()) x=(x<<1)+(x<<3)+ch-'0';
    return x*op;
}
int n,m,ans,tot,rt[N<<2],ls[M],rs[M],val[M];
int ksm(int x,int p){
    int ret=1;
    for (; p; p>>=1,x=(ll)x*x%mod) if (p&1) ret=(ll)ret*x%mod;
    return ret;
}
int inv(int x){
    return ksm(x,mod-2);
}
int merge(int x,int y){
    return ((ll)x*y%mod+(ll)(1+mod-x)*(1+mod-y)%mod)%mod;
}
void upd2(int &o,int l,int r,int x,int y,int p){
    if (!o) o=++tot,val[o]=1;
    if (x<=l && r<=y){
        val[o]=merge(val[o],p);
        return;
    }
    int mid=l+r>>1;
    if (x<=mid) upd2(ls[o],l,mid,x,y,p);
    if (y>mid) upd2(rs[o],mid+1,r,x,y,p);
}
void qry2(int o,int l,int r,int x){
    if (!o) return;
    ans=merge(ans,val[o]);
    if (l==r) return;
    int mid=l+r>>1;
    if (x<=mid) qry2(ls[o],l,mid,x); else qry2(rs[o],mid+1,r,x);
}
void upd(int o,int l,int r,int x,int y,int xx,int yy,int p){
    if (x<=l && r<=y){
        upd2(rt[o],0,n,xx,yy,p);
        return;
    }
    int mid=l+r>>1;
    if (x<=mid) upd(lc,l,mid,x,y,xx,yy,p);
    if (y>mid) upd(rc,mid+1,r,x,y,xx,yy,p);
}
void qry(int o,int l,int r,int x,int y){
    if (rt[o]) qry2(rt[o],0,n,y);
    if (l==r) return;
    int mid=l+r>>1;
    if (x<=mid) qry(lc,l,mid,x,y); else qry(rc,mid+1,r,x,y);
}
int main(){
    n=read(); m=read(); int now=0;
    while (m--){
        int opt=read(),l=read(),r=read();
        if (opt==1){//修改
            int p=inv(r-l+1),p2=2ll*p%mod;//二維區間更新
            upd(1,0,n,0,l-1,l,r,1+mod-p);
            if (r<n) upd(1,0,n,l,r,r+1,n,1+mod-p);
            upd(1,0,n,l,r,l,r,1+mod-p2);
            now^=1;
        } else{
            ans=1;
            if (l==1 && (now&1)){ qry(1,0,n,0,r); ans=(1+mod-ans)%mod; }
            else qry(1,0,n,l-1,r);//二維單點查詢
            printf("%d\n",ans);
        }
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章