社区讨论

萌新求助,整体二分全 TLE 了,代码有注释

P1527[国家集训队] 矩阵乘法参与者 11已保存回复 16

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
16 条
当前快照
1 份
快照标识符
@lvru5wl3
此快照首次捕获于
2024/05/04 16:22
2 年前
此快照最后确认于
2024/05/04 18:25
2 年前
查看原帖
RT,我也不知道为什么,总之挂了。
CPP
#include<bits/stdc++.h>
using namespace std;
const int N=5e2+10;
const int M=6e4+10;
const int inf=1e9;
inline int _abs(int x){if(x>0) return x;return -x;}

struct BIT{//二维树状树组
	int tree[N][N];
	int lowbit(int x){
		return x&(-x);
	}
	
	void modify(int x,int y,int val){
		while(x<N){
			int ty=y;
			while(ty<N){
				tree[x][ty]+=val;
				ty+=lowbit(ty);
			}
			x+=lowbit(x);
		}
	}
	
	int q(int x,int y){
		int ans=0;
		while(x){
			int ty=y;
			while(ty){
				ans+=tree[x][ty];
				ty-=lowbit(ty);
			}
			x-=lowbit(x);
		}
		return ans;
	}
	
	int query(int x,int y,int _x,int _y){//(x,y) left-up  (_x,_y) right-down
		return q(_x,_y)-q(_x,y-1)-q(x-1,_y)+q(x-1,y-1);
	}
}bit;

struct queries{
	int l,r,_l,_r,id,opt,k;
}t[M+N*N]; int F[M],cnt1,cnt2,cnt;
queries q1[M+N*N],q2[M+N*N];

void solve(int l,int r,int L,int R){
	if(l>r) return;//没东西了 就return
	//cout<<l<<" "<<r<<" "<<L<<" "<<R<<"\n";
	//for(int i=l;i<=r;i++){
	//	cout<<t[i].l<<" "<<t[i].r<<" "<<t[i]._l<<" "<<t[i]._r<<" "<<t[i].id<<" "<<t[i].opt<<" "<<t[i].k<<"\n";
	//}
	if(L==R){//如果到一个区间上,就是答案
		for(int i=l;i<=r;i++){
			if(t[i].opt==1) F[t[i].id]=L;
		}
		return;
	}
	
	int mid=(L+R)>>1; cnt1=cnt2=0;
	for(int i=l;i<=r;i++){
		if(t[i].opt==0){//如果是数字,就加上去
			if(t[i].k<=mid){
				bit.modify(t[i].l,t[i].r,1);
				q1[++cnt1]=t[i];
			}else{
				q2[++cnt2]=t[i];
			}
		}else{//如果是查询,就二分
			int tmp=bit.query(t[i].l,t[i].r,t[i]._l,t[i]._r);
			//cout<<t[i].id<<" "<<tmp<<"\n";
			if(tmp>=t[i].k){
				q1[++cnt1]=t[i];
			}else{
				t[i].k-=tmp;
				q2[++cnt2]=t[i];
			}
		}
	}
	
	for(int i=1;i<=cnt1;i++){//树状数组回退
		if(q1[i].opt==0) bit.modify(q1[i].l,q1[i].r,-1);
	}
	//合并左右边
	for(int i=1;i<=cnt1;i++) t[l+i-1]=q1[i];
	for(int i=1;i<=cnt2;i++) t[l+cnt1+i-1]=q2[i];
	solve(l,l+cnt1-1,L,mid);//递归
	solve(l+cnt1,r,mid+1,R);
}

int a[N][N];
int qwq[N*N],res;

void fake_main(){
	int n,q; cin>>n>>q;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			cin>>a[i][j]; qwq[++res]=a[i][j];
			//t[++cnt]={i,j,0,0,0,0,a[i][j]};
		}
	}
	sort(qwq+1,qwq+res+1);//离散化
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			a[i][j]=lower_bound(qwq+1,qwq+res+1,a[i][j])-qwq;
			t[++cnt]={i,j,0,0,0,0,a[i][j]};
		}
	}
	
	for(int i=1;i<=q;i++){
		int l,r,_l,_r,k; cin>>l>>r>>_l>>_r>>k;
		t[++cnt]={l,r,_l,_r,i,1,k};
	}//存入查询
	
	solve(1,cnt,1,n*n);//二分
	
	for(int i=1;i<=q;i++){
		cout<<qwq[F[i]]<<"\n";
	}
}

signed main(){
	ios::sync_with_stdio(false);
	int t; t=1;
	while(t--) fake_main();
}

回复

16 条回复,欢迎继续交流。

正在加载回复...