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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

中国石油大学(华东)暑期集训--二进制(BZOJ5294)【线段树】

發(fā)布時間:2023/11/30 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 中国石油大学(华东)暑期集训--二进制(BZOJ5294)【线段树】 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

問題 C: 二進(jìn)制

時間限制: 1 Sec??內(nèi)存限制: 128 MB
提交: 8??解決: 2
[提交] [狀態(tài)] [討論版] [命題人:]

題目描述

pupil發(fā)現(xiàn)對于一個十進(jìn)制數(shù),無論怎么將其的數(shù)字重新排列,均不影響其是不是3的倍數(shù)。他想研究對于二進(jìn)制,是否也有類似的性質(zhì)。于是他生成了一個長為n的二進(jìn)制串,希望你對于這個二進(jìn)制串的一個子區(qū)間,能求出其有多少位置不同的連續(xù)子串,滿足在重新排列后(可包含前導(dǎo)0)是一個3的倍數(shù)。兩個位置不同的子區(qū)間指開始位置不同或結(jié)束位置不同。由于他想嘗試盡量多的情況,他有時會修改串中的一個位置,并且會進(jìn)行多次詢問。

輸入

輸入第一行包含一個正整數(shù)n,表示二進(jìn)制數(shù)的長度。
之后一行n個空格隔開的整數(shù),保證均是0或1,表示該二進(jìn)制串。
之后一行一個整數(shù)m,表示詢問和修改的總次數(shù)。
之后m行每行為1 i,表示pupil修改了串的第i個位置(0變成1或1變成0),或2 l r,表示pupil詢問的子區(qū)間是[l,r]。
串的下標(biāo)從1開始。

輸出

對于每次詢問,輸出一行一個整數(shù)表示對應(yīng)該詢問的結(jié)果。


樣例輸入

4 1 0 1 0 3 2 1 3 1 3 2 3 4

樣例輸出

2 3

提示

對于第一個詢問,區(qū)間[2,2]只有數(shù)字0,是3的倍數(shù),區(qū)間[1,3]可以重排成011(2)=3(10),是3的倍數(shù),其他區(qū)間均不能重排成3的倍數(shù)。
對于第二個詢問,全部三個區(qū)間均能重排成3的倍數(shù)(注意00也是合法的)。

對于20%的數(shù)據(jù),1≤n,m≤100;
對于50%的數(shù)據(jù),1≤n,m≤5000;
對于100%的數(shù)據(jù),1≤n,m≤100000,l≤r。


Solution: 設(shè)cnt0,cnt1分別為[l,r]區(qū)間內(nèi)的1和0的個數(shù),易得: 1. if cnt1==1 => 不可整除3 2. if cnt1&1 and cnt0<2 => 不可整除3

  簡單證明上述結(jié)論:

    顯然結(jié)論1是成立的(1<<n不可能整除3),當(dāng)cnt1為偶數(shù)時,顯然也一定可以整除3,而當(dāng)cnt1&1時:

    先考慮這種情況,將一個二進(jìn)制數(shù)將其兩位兩位拆分并求和得到sum,顯然如果 sum%3==0 ,則該二進(jìn)制數(shù)的十進(jìn)制一定可以整除3。

    如:111010001=>(01,11,01,00,01),sum=1+3+1+0+1=6。

    那么,對于奇數(shù)個1,從中挑出cnt1-3個“1”兩兩組合,確保對sum%3的結(jié)果無貢獻(xiàn)后,再看剩下的3個“1”的情況:

      ①、sum(111)=4 無法整除。【區(qū)間內(nèi)無0】

      ②、sum(1101)=4,sum(1011)=5 無法整除。【區(qū)間內(nèi)只含有一個0】

      ③、sum(10101)=3 可整除。【區(qū)間內(nèi)至少含有兩個0】

  綜上:

    我們用線段樹去維護(hù)上述兩種不合法情況,再用【總數(shù)-不合法數(shù)=合法數(shù)】來得到答案。

    其中,dl/dr[2][2] 代表經(jīng)過左右節(jié)點(diǎn)后:cnt0=0/1,cnt1&1?1:0。

    fl/fr[3] 代表經(jīng)過左右節(jié)點(diǎn)后:滿足(cnt1==1 and cnt0==0/1)的方案數(shù)。

    L/R表示經(jīng)過左右節(jié)點(diǎn)后,連續(xù)0的長度。

代碼:

1 #include <iostream> 2 #include <string> 3 #include <cstdio> 4 #include <cmath> 5 #include <cstring> 6 #include <algorithm> 7 #include <vector> 8 #include <queue> 9 #include <deque> 10 #include <map> 11 #include <set> 12 #define range(i,a,b) for(auto i=a;i<=b;++i) 13 #define LL long long 14 #define ULL unsigned long long 15 #define elif else if 16 #define itrange(i,a,b) for(auto i=a;i!=b;++i) 17 #define rerange(i,a,b) for(auto i=a;i>=b;--i) 18 #define fill(arr,tmp) memset(arr,tmp,sizeof(arr)) 19 #define IOS ios::sync_with_stdio(false);cin.tie(0) 20 using namespace std; 21 int n,m,op,l,r,A[int(1e5+5)]; 22 class SegTree{ 23 private: 24 struct node{ 25 LL s,dl[2][2],dr[2][2],fl[3],fr[3],L,R; 26 int cnt0,cnt1; 27 void reset(){ 28 range(i,0,1)range(j,0,1)dl[i][j]=dr[i][j]=0; 29 fl[0]=fl[1]=fr[0]=fr[1]=fl[2]=fr[2]=L=R=s=cnt0=cnt1=0; 30 } 31 node(){reset();} 32 }tree[int(1e5+5)<<2]; 33 node comb(node A,node B){ 34 node tmp; 35 range(i,0,1)range(j,0,1){ 36 tmp.dl[i][j]+=A.dl[i][j]; 37 tmp.dr[i][j]+=B.dr[i][j]; 38 if(i>=A.cnt0)tmp.dl[i][j]+=B.dl[i-A.cnt0][j^(A.cnt1&1)]; 39 if(i>=B.cnt0)tmp.dr[i][j]+=A.dr[i-B.cnt0][j^(B.cnt1&1)]; 40 } 41 range(i,0,2){ 42 tmp.fl[i]+=A.fl[i]; 43 tmp.fr[i]+=B.fr[i]; 44 if(!A.cnt1)tmp.fl[min(2,i+A.cnt0)]+=B.fl[i]; 45 if(!B.cnt1)tmp.fr[min(2,i+B.cnt0)]+=A.fr[i]; 46 } 47 if(A.cnt1==1 and B.L){ 48 ++tmp.fl[min(2LL,A.cnt0+B.L)]; 49 tmp.fl[2]+=B.L-1; 50 } 51 if(B.cnt1==1 and A.R){ 52 ++tmp.fr[min(2LL,B.cnt0+A.R)]; 53 tmp.fr[2]+=A.R-1; 54 } 55 tmp.L=(!A.cnt1?A.cnt0+B.L:A.L);tmp.R=(!B.cnt1?B.cnt0+A.R:B.R); 56 tmp.cnt0=A.cnt0+B.cnt0;tmp.cnt1=A.cnt1+B.cnt1;tmp.s+=A.s+B.s; 57 tmp.s+=A.dr[0][1]*(B.dl[1][0]+B.dl[0][0])+A.dr[1][0]*B.dl[0][1]; 58 tmp.s+=A.dr[0][0]*(B.dl[1][1]+B.dl[0][1])+A.dr[1][1]*B.dl[0][0]; 59 if(B.L)tmp.s+=(A.fr[1]+A.fr[2])*B.L+A.fr[0]*(B.L-1); 60 if(A.R)tmp.s+=(B.fl[1]+B.fl[2])*A.R+B.fl[0]*(A.R-1); 61 return tmp; 62 } 63 void pushup(node &tmp,int x){ 64 tmp.reset(); 65 if(x)tmp.s=tmp.fl[0]=tmp.fr[0]=tmp.dl[0][1]=tmp.dr[0][1]=tmp.cnt1=1; 66 else tmp.dl[1][0]=tmp.dr[1][0]=tmp.L=tmp.R=tmp.cnt0=1; 67 }; 68 public: 69 void build(int l,int r,int rt=1){ 70 if(l==r){ 71 pushup(tree[rt],A[l]); 72 return; 73 } 74 int m=(l+r)>>1; 75 build(l,m,rt<<1); 76 build(m+1,r,rt<<1|1); 77 tree[rt]=comb(tree[rt<<1],tree[rt<<1|1]); 78 } 79 void update(int l,int r,int rt,int L){ 80 if(l==r){ 81 pushup(tree[rt],A[l]); 82 return; 83 } 84 int m=(l+r)>>1; 85 if(L<=m)update(l,m,rt<<1,L); 86 else update(m+1,r,rt<<1|1,L); 87 tree[rt]=comb(tree[rt<<1],tree[rt<<1|1]); 88 } 89 node query(int l,int r,int rt,int L,int R){ 90 if(L<=l and r<=R)return tree[rt]; 91 int m=(l+r)>>1; 92 if(R<=m)return query(l,m,rt<<1,L,R); 93 if(L>m)return query(m+1,r,rt<<1|1,L,R); 94 return comb(query(l,m,rt<<1,L,m),query(m+1,r,rt<<1|1,m+1,R)); 95 } 96 }segTree; 97 void init(){ 98 scanf("%d",&n); 99 range(i,1,n)scanf("%d",A+i); 100 segTree.build(1,n); 101 scanf("%d",&m); 102 } 103 void solve(){ 104 while(m--){ 105 scanf("%d%d",&op,&l); 106 if(op&1)A[l]^=1,segTree.update(1,n,1,l); 107 else{ 108 scanf("%d",&r); 109 printf("%lld\n",1LL*(r-l+1)*(r-l+2)/2-segTree.query(1,n,1,l,r).s); 110 } 111 } 112 } 113 int main() { 114 init(); 115 solve(); 116 return 0; 117 } View Code

?

轉(zhuǎn)載于:https://www.cnblogs.com/Rhythm-/p/9455281.html

創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎勵來咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎

總結(jié)

以上是生活随笔為你收集整理的中国石油大学(华东)暑期集训--二进制(BZOJ5294)【线段树】的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。