日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【BZOJ3821/UOJ46】玄学(二进制分组,线段树)

發布時間:2025/3/15 编程问答 14 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【BZOJ3821/UOJ46】玄学(二进制分组,线段树) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

【BZOJ3821/UOJ46】玄學(二進制分組,線段樹)

題面

BZOJ
UOJ

題解

嗚,很好的題目啊QwQ。
離線做法大概可以線段樹分治,或者直接點記錄左右兩次操作時的結果,兩個除一下就可以直接計算。
強制在線的話,一般而言,分治在線就弄成二進制分組。把所有修改操作進行二進制分組,每次新加入一個修改操作的時候考慮和前面其他的操作合并,提前構出來線段樹,按照次序插入。如果一個節點的左右兒子都填滿了修改操作的話,那么把它的兩個兒子的值進行合并。然而我們發現并不可能每個節點維護一棵線段樹來表示所有的位置的值,實際上,因為每次修改影響的都是一段區間,所以可以用\(vector\)記錄修改區間,每次只需要把左右兒子的所有斷點合并起來分段就好了,這樣子每個修改操作每次貢獻\(1\)個斷點,所以在整個線段樹上最多貢獻\(log\)個斷點,直接暴力合并就可以了。
這樣子每次查詢就可以直接在線段樹上查詢啦。
似乎說的不清楚,看看代碼就懂了

#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<cmath> #include<algorithm> #include<vector> using namespace std; #define ll long long #define MAX 100100 #define lson (now<<1) #define rson (now<<1|1) inline int read() {int x=0;bool t=false;char ch=getchar();while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();if(ch=='-')t=true,ch=getchar();while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();return t?-x:x; } int type,n,Q,tot,m,lans,a[MAX]; struct Node{int l,r,a,b;}t[MAX<<2]; void calc(int &a,int &b,int x,int y){a=1ll*a*x%m;b=(1ll*b*x+y)%m;} Node operator+(Node a,Node b){calc(a.a,a.b,b.a,b.b);return a;} vector<Node> s[MAX<<2]; void Build(int now,int l,int r) {s[now].push_back((Node){1,n,1,0});if(l==r)return;int mid=(l+r)>>1;Build(lson,l,mid);Build(rson,mid+1,r); } void pushup(int now) {s[now].clear();int l1=s[lson].size(),l2=s[rson].size();for(int i=0,j=0,l=0;i<l1&&j<l2;){int a=s[lson][i].a,b=s[lson][i].b;calc(a,b,s[rson][j].a,s[rson][j].b);if(s[lson][i].r<=s[rson][j].r){s[now].push_back((Node){l+1,s[lson][i].r,a,b});l=s[lson][i].r;if(s[lson][i].r==s[rson][j].r)++i,++j;else ++i;}else{s[now].push_back((Node){l+1,s[rson][j].r,a,b});l=s[rson][j].r;++j;}}return; } bool Modify(int now,int l,int r,int p,Node a) {if(l==r){if(a.l!=1)s[now].push_back((Node){1,a.l-1,1,0});s[now].push_back(a);if(a.r!=n)s[now].push_back((Node){a.r+1,n,1,0});return true;}int mid=(l+r)>>1;if(p<=mid){Modify(lson,l,mid,p,a);return false;}else{bool fl=Modify(rson,mid+1,r,p,a);if(fl)pushup(now);return true;} } Node Query(int now,int l,int r,int L,int R,int k) {if(L==l&&r==R){int l=0,r=s[now].size();while(l<=r){int mid=(l+r)>>1;if(s[now][mid].l<=k&&k<=s[now][mid].r)return s[now][mid];if(s[now][mid].r<k)l=mid+1;else r=mid-1;}}int mid=(l+r)>>1;if(R<=mid)return Query(lson,l,mid,L,R,k);if(L>mid)return Query(rson,mid+1,r,L,R,k);return Query(lson,l,mid,L,mid,k)+Query(rson,mid+1,r,mid+1,R,k); }int main() {type=read();n=read();m=read();for(int i=1;i<=n;++i)a[i]=read();Q=read();while(Q--){int opt=read(),l=read(),r=read();if(type&1)l^=lans,r^=lans;if(opt==1){int a=read(),b=read();++tot;Modify(1,1,100000,tot,(Node){l,r,a,b});}else{int x=read();if(type&1)x^=lans;Node u=Query(1,1,100000,l,r,x);lans=(1ll*u.a*a[x]+u.b)%m;printf("%d\n",lans);}}return 0; }

轉載于:https://www.cnblogs.com/cjyyb/p/10087923.html

總結

以上是生活随笔為你收集整理的【BZOJ3821/UOJ46】玄学(二进制分组,线段树)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。