time limit: 20 sec
memory limit: 256 mb
submit: 1183
solved: 504 [
submit][
status][
discuss]
給你乙個n*n的矩陣,不用算矩陣乘法,但是每次詢問乙個子矩形的第k小數。
第一行兩個數n,q,表示矩陣大小和詢問組數;
接下來n行n列一共n*n個數,表示這個矩陣;
再接下來q行每行5個數描述乙個詢問:x1,y1,x2,y2,k表示找到以(x1,y1)為左上角、以(x2,y2)為右下角的子矩形中的第k小數。
對於每組詢問輸出第k小的數。
2 22 13 4
1 2 1 2 1
1 1 2 2 313
矩陣中數字是109以內的非負整數;
20%的資料:n<=100,q<=1000;
40%的資料:n<=300,q<=10000;
60%的資料:n<=400,q<=30000;
100%的資料:n<=500,q<=60000。 二分
+分治+二維樹狀陣列
(方法和題目名字一點關係都沒有)
二分答案mid,然後將所有數值小於等於mid的插入到二維樹狀陣列中。
詢問每個矩形中小於mid的元素個數,如果數量大於等於k則放左邊,否則放右邊。
左邊的二分範圍為[1,mid],右邊的答案範圍為[mid+1,n],繼續向下分治。
#include#include#include#include#include#include#define f(i,j,n) for(int i=j;i<=n;i++)
#define d(i,j,n) for(int i=j;i>=n;i--)
#define ll long long
#define maxn 505
#define maxm 60005
#define inf 1000000000
using namespace std;
int n,m,mx,mn=inf,cnt,t;
int s[maxn][maxn],ans[maxm],id[maxm],tmp[maxm];
struct dataa[maxn*maxn];
struct quesp[maxm];
inline int read()
while (ch>='0'&&ch<='9')
return x*f;
}inline bool cmp(data a,data b)
f(i,l,r) id[i]=tmp[i];
solve(l,l1-1,l,mid);solve(l1,r,mid+1,r);
}int main()
sort(a+1,a+cnt+1,cmp);
f(i,1,m) p[i].x1=read(),p[i].y1=read(),p[i].x2=read(),p[i].y2=read(),p[i].k=read();
f(i,1,m) id[i]=i;
solve(1,m,0,mx+1);
f(i,1,m) printf("%d\n",ans[i]);
return 0;
}
BZOJ 2738 矩陣乘法
卡時卡的我心塞啊 因為插入操作太多而且沒有順序我們需要在sort後的插入操作上滾來滾去 其實並不需要排序opt陣列,而用int下標排序可避免複製的時間過長。include include include include include define maxn 510 using namespace ...
bzoj2738 矩陣乘法
description 給你乙個n n的矩陣,不用算矩陣乘法,但是每次詢問乙個子矩形的第k小數。input 第一行兩個數n,q,表示矩陣大小和詢問組數 接下來n行n列一共n n個數,表示這個矩陣 再接下來q行每行5個數描述乙個詢問 x1,y1,x2,y2,k表示找到以 x1,y1 為左上角 以 x2...
bzoj2738 矩陣乘法
m id,每次把權值小於等於mi d 的數對應位置上 1 可以用二維bit實現 然後掃瞄當前的詢問,對於乙個詢問看它對應的那個子矩形中已經插入了幾個數,如果插入的數的個數比詢問的 k 大,就說明列舉的答案過大,就把當前詢問加入左邊,否則加入右邊。然後分治下去。整體二分 二維bit include i...