UOJ#291. 【ZJOI2017】树状数组 树套树
原文链接https://www.cnblogs.com/zhouzhendong/p/UOJ291.html
题解
结论:这个写错的树状数组支持的是后缀加和后缀求和。这里的后缀求和在 x = 0 的时候比较特殊,返回 0 。
于是我们需要查询 v[L-1] 和 v[R] 相同的概率是多少。
我们可以用树套树维护一下左端点在一个区间内,右端点在另一个区间内的修改操作使得对应点发生变化的概率。
注意 L = 1 要特判。
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 | #include <bits/stdc++.h> #define clr(x) memset(x,0,sizeof (x)) #define For(i,a,b) for (int i=a;i<=b;i++) #define Fod(i,b,a) for (int i=b;i>=a;i--) #define pb push_back #define mp make_pair #define fi first #define se second #define _SEED_ ('C'+'L'+'Y'+'A'+'K'+'I'+'O'+'I') #define outval(x) printf(#x" = %d\n",x) #define outvec(x) printf("vec "#x" = ");for (auto _v : x)printf("%d ",_v);puts("") #define outtag(x) puts("----------"#x"----------") using namespace std; typedef long long LL; LL read(){ LL x=0,f=0; char ch= getchar (); while (! isdigit (ch)) f|=ch== '-' ,ch= getchar (); while ( isdigit (ch)) x=(x<<1)+(x<<3)+(ch^48),ch= getchar (); return f?-x:x; } const int N=100005,mod=998244353; int Pow( int x, int y){ int ans=1; for (;y;y>>=1,x=(LL)x*x%mod) if (y&1) ans=(LL)ans*x%mod; return ans; } int Pmul( int x, int y){ return ((LL)x*(1-y)+(LL)y*(1-x))%mod; } int n,m; namespace Seg{ const int S=N*305; int ls[S],rs[S],cnt=0; int v1[S],v2[S]; void update( int &rt, int L, int R, int x, int v){ if (!rt) rt=++cnt,v1[rt]=v2[rt]=0; v1[rt]=Pmul(v1[rt],v); v2[rt]=Pmul(v2[rt],v*2%mod); if (L==R) return ; int mid=(L+R)>>1; if (x<=mid) update(ls[rt],L,mid,x,v); else update(rs[rt],mid+1,R,x,v); } int Q1( int rt, int L, int R, int xL, int xR){ if (!rt||xR<L||R<xL) return 0; if (xL<=L&&R<=xR) return v1[rt]; int mid=(L+R)>>1; return Pmul(Q1(ls[rt],L,mid,xL,xR),Q1(rs[rt],mid+1,R,xL,xR)); } int Q2( int rt, int L, int R, int xL, int xR){ if (!rt||xR<L||R<xL) return 0; if (xL<=L&&R<=xR) return v2[rt]; int mid=(L+R)>>1; return Pmul(Q2(ls[rt],L,mid,xL,xR),Q2(rs[rt],mid+1,R,xL,xR)); } } int root[N<<2]; void upd( int rt, int L, int R, int x, int y, int v){ Seg::update(root[rt],1,n,y,v); if (L==R) return ; int mid=(L+R)>>1,ls=rt<<1,rs=ls|1; if (x<=mid) upd(ls,L,mid,x,y,v); else upd(rs,mid+1,R,x,y,v); } int Q1( int rt, int L, int R, int xL, int xR, int yL, int yR){ if (xL>xR||yL>yR||R<xL||L>xR) return 0; if (xL<=L&&R<=xR) return Seg::Q1(root[rt],1,n,yL,yR); int mid=(L+R)>>1,ls=rt<<1,rs=ls|1; return Pmul(Q1(ls,L,mid,xL,xR,yL,yR),Q1(rs,mid+1,R,xL,xR,yL,yR)); } int Q2( int rt, int L, int R, int xL, int xR, int yL, int yR){ if (xL>xR||yL>yR||R<xL||L>xR) return 0; if (xL<=L&&R<=xR) return Seg::Q2(root[rt],1,n,yL,yR); int mid=(L+R)>>1,ls=rt<<1,rs=ls|1; return Pmul(Q2(ls,L,mid,xL,xR,yL,yR),Q2(rs,mid+1,R,xL,xR,yL,yR)); } int main(){ n=read(),m=read(); int cnt=0; while (m--){ int type=read(),L=read(),R=read(); if (type==1){ cnt^=1; upd(1,1,n,L,R,Pow(R-L+1,mod-2)); } else { L--; int vL=Q1(1,1,n,1,L,L,R-1); int vR=Q1(1,1,n,L+1,R,R,n); int vm=Q2(1,1,n,1,L,R,n); int ans=Pmul(vm,Pmul(vL,vR)); if (L||!cnt) ans=(1LL-ans)%mod; ans=(ans+mod)%mod; printf ( "%d\n" ,ans); } } return 0; } |
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 为什么说在企业级应用开发中,后端往往是效率杀手?
· 用 C# 插值字符串处理器写一个 sscanf
· Java 中堆内存和栈内存上的数据分布和特点
· 开发中对象命名的一点思考
· .NET Core内存结构体系(Windows环境)底层原理浅谈
· 为什么说在企业级应用开发中,后端往往是效率杀手?
· 本地部署DeepSeek后,没有好看的交互界面怎么行!
· DeepSeek 解答了困扰我五年的技术问题。时代确实变了!
· 趁着过年的时候手搓了一个低代码框架
· 推荐一个DeepSeek 大模型的免费 API 项目!兼容OpenAI接口!