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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

BZOJ.2738.矩阵乘法(整体二分 二维树状数组)

發(fā)布時(shí)間:2023/11/30 编程问答 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 BZOJ.2738.矩阵乘法(整体二分 二维树状数组) 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

題目鏈接 BZOJ
洛谷

整體二分。把求序列第K小的樹狀數(shù)組改成二維樹狀數(shù)組就行了。
初始答案區(qū)間有點(diǎn)大,離散化一下。

因?yàn)檫@題是一開始給點(diǎn),之后詢問,so可以先處理該區(qū)間值在l~mid的修改,再處理詢問。即二分標(biāo)準(zhǔn)可以直接用點(diǎn)的標(biāo)號(hào)。
結(jié)構(gòu)體的賦值可以改為賦值操作的編號(hào)。(這樣內(nèi)存沒那么連續(xù)?想多了你)

改了半下午,優(yōu)化了500ms。。

//6980kb 10584ms 好慢啊QAQ //4208ms 7.59MB #include <cstdio> #include <cctype> #include <algorithm> #define lb(x) ((x)&-(x)) //#define gc() getchar() #define MAXIN 500000 #define gc() (SS==TT&&(TT=(SS=IN)+fread(IN,1,MAXIN,stdin),SS==TT)?EOF:*SS++) const int N=505,M=60005;int n,m,Ans[M],q[M],q1[M],q2[M]; char IN[MAXIN],*SS=IN,*TT=IN; struct Point {int x,y,val;Point() {}Point(int x,int y,int val):x(x),y(y),val(val) {}bool operator <(const Point &a)const{return val<a.val;} }pt[N*N]; inline int read(); struct Operation//Query {int K,x1,y1,x2,y2;inline void Input(){x1=read(),y1=read(),x2=read(),y2=read(),K=read();} }op[M];inline int read() {int now=0;register char c=gc();for(;!isdigit(c);c=gc());for(;isdigit(c);now=now*10+c-'0',c=gc());return now; } namespace T {int n,t[N][N];inline void Modify(int x,int y,int v){for(int i=x; i<=n; i+=lb(i))for(int j=y; j<=n; j+=lb(j)) t[i][j]+=v;}inline void Clear(int x,int y){for(int i=x; i<=n; i+=lb(i))for(int j=y; j<=n; j+=lb(j))if(t[i][j]) t[i][j]=0; else break;}inline int Query(int x,int y){int res=0;for(int i=x; i; i^=lb(i))for(int j=y; j; j^=lb(j)) res+=t[i][j];return res;}inline int Query_Area(Operation q){//prefix sumreturn Query(q.x2,q.y2)-Query(q.x1-1,q.y2)-Query(q.x2,q.y1-1)+Query(q.x1-1,q.y1-1);} } void Solve(int l,int r,int h,int t) {if(h>t) return;if(l==r){for(int i=h; i<=t; ++i) Ans[q[i]]/*[op[q[i]].pos]*/=pt[l].val;return;}int mid=l+r>>1, t1=0, t2=0;for(int i=l; i<=mid; ++i) T::Modify(pt[i].x,pt[i].y,1);for(int now,tmp,i=h; i<=t; ++i){now=q[i], tmp=T::Query_Area(op[now]);if(tmp>=op[now].K) q1[t1++]=now;else op[now].K-=tmp, q2[t2++]=now;}for(int i=l; i<=mid; ++i) T::Clear(pt[i].x,pt[i].y);for(int i=0; i<t1; ++i) q[h+i]=q1[i];for(int i=0; i<t2; ++i) q[h+t1+i]=q2[i];Solve(l,mid,h,h+t1-1), Solve(mid+1,r,h+t1,t); }int main() {T::n=n=read(), m=read();int tot=0;for(int i=1; i<=n; ++i)for(int j=1; j<=n; ++j) pt[++tot]=Point(i,j,read());std::sort(pt+1,pt+1+tot);for(int i=1; i<=m; ++i) q[i]=i, op[i].Input();Solve(1,tot,1,m);for(int i=1; i<=m; ++i) printf("%d\n",Ans[i]);return 0; }

優(yōu)化前:

//4680ms 17.75MB #include <cstdio> #include <cctype> #include <algorithm> #define lb(x) ((x)&-(x)) //#define gc() getchar() #define MAXIN 60000 #define gc() (SS==TT&&(TT=(SS=IN)+fread(IN,1,MAXIN,stdin),SS==TT)?EOF:*SS++) const int N=505,M=60005+N*N;int n,m,Q,cnt,A[N*N],Ans[60005]; char IN[MAXIN],*SS=IN,*TT=IN; struct Operation {int K,x1,y1,x2,y2,pos;//K=0: Modify (x1,y1):=posOperation() {}Operation(int K,int x1,int y1,int x2,int y2,int pos):K(K),x1(x1),y1(y1),x2(x2),y2(y2),pos(pos) {} }q[M],q1[M],q2[M];inline int read() {int now=0;register char c=gc();for(;!isdigit(c);c=gc());for(;isdigit(c);now=now*10+c-'0',c=gc());return now; } namespace T {int n,t[N][N];inline void Modify(int x,int y,int v){for(int i=x; i<=n; i+=lb(i))for(int j=y; j<=n; j+=lb(j)) t[i][j]+=v;}inline void Clear(int x,int y){for(int i=x; i<=n; i+=lb(i))for(int j=y; j<=n; j+=lb(j))if(t[i][j]) t[i][j]=0; else break;}inline int Query(int x,int y){int res=0;for(int i=x; i; i^=lb(i))for(int j=y; j; j^=lb(j)) res+=t[i][j];return res;}inline int Query_Area(Operation q){//prefix sumreturn Query(q.x2,q.y2)-Query(q.x1-1,q.y2)-Query(q.x2,q.y1-1)+Query(q.x1-1,q.y1-1);} } void Solve(int l,int r,int h,int t) {if(h>t) return;if(l==r){for(int i=h; i<=t; ++i) if(q[i].K) Ans[q[i].pos]=A[l];return;}bool goon=0;for(int i=h; i<=t; ++i) if(q[i].K) {goon=1; break;}if(!goon) return;int mid=l+r>>1, midV=A[mid], t1=0, t2=0;for(int i=h; i<=t; ++i)if(q[i].K){int tmp=T::Query_Area(q[i]);//這樣好像少做幾次加法!但是多copy兩個(gè)int。。(你夠了→_→)if(tmp>=q[i].K) q1[t1++]=q[i];else q[i].K-=tmp, q2[t2++]=q[i];}else{if(q[i].pos<=midV) T::Modify(q[i].x1,q[i].y1,1), q1[t1++]=q[i];else q2[t2++]=q[i];}for(int i=0; i<t1; ++i) if(!q1[i].K) T::Clear(q1[i].x1,q1[i].y1);for(int i=0; i<t1; ++i) q[h+i]=q1[i];for(int i=0; i<t2; ++i) q[h+t1+i]=q2[i];Solve(l,mid,h,h+t1-1), Solve(mid+1,r,h+t1,t); }int main() {T::n=n=read(), m=read(), Q=0;for(int i=1; i<=n; ++i)for(int j=1; j<=n; ++j) q[++Q]=Operation(0,i,j,0,0,A[Q]=read());std::sort(A+1,A+1+Q), cnt=1;for(int i=2; i<=Q; ++i) if(A[i]!=A[i-1]) A[++cnt]=A[i];for(int x1,y1,x2,y2,i=1; i<=m; ++i)x1=read(),y1=read(),x2=read(),y2=read(),q[++Q]=Operation(read(),x1,y1,x2,y2,i);Solve(1,cnt,1,Q);for(int i=1; i<=m; ++i) printf("%d\n",Ans[i]);return 0; }

轉(zhuǎn)載于:https://www.cnblogs.com/SovietPower/p/9234335.html

總結(jié)

以上是生活随笔為你收集整理的BZOJ.2738.矩阵乘法(整体二分 二维树状数组)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

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