bzoj2738 矩阵乘法
题目链接:bzoj2738
题目大意:给你一个N*N的矩阵,不用算矩阵乘法,但是每次询问一个子矩形的第K小数。
【= =题目在逗我吧
题解:
整体二分
不过是不带修改的区间第k小的升级版。
改用二维树状数组维护就好了。
可能是我常数太大代码太丑?狂TLE,最后加了个读优卡过了。。。
#include<cstdio> #include<cstdlib> #include<cstring> #include<iostream> #include<algorithm> using namespace std; #define maxn 351000 #define N 600 #define inf 1e9 struct node { int x1,x2,y1,y2,c,tg,ans; }q[maxn]; int n,m,id[maxn],c[N][N]; int tol[maxn],tor[maxn]; inline int read() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9') {if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9') {x=x*10+ch-'0';ch=getchar();} return x*f; } int lowbit(int x){return x&(-x);} void change(int x,int y,int k) { for (int i=x;i<=n;i+=lowbit(i)) for (int j=y;j<=n;j+=lowbit(j)) c[i][j]+=k; } int query(int x,int y) { int ret=0; for (int i=x;i>0;i-=lowbit(i)) for (int j=y;j>0;j-=lowbit(j)) ret+=c[i][j]; return ret; } void solve(int head,int tail,int l,int r) { if (head>tail) return; int lnum=0,rnum=0,i,mid=(l+r)>>1; if (l==r) { for (i=head;i<=tail;i++) if (q[id[i]].tg==2) q[id[i]].ans=l; return; } for (i=head;i<=tail;i++) if (q[id[i]].tg==1) { if (q[id[i]].c<=mid) tol[++lnum]=id[i],change(q[id[i]].x1,q[id[i]].y1,1); else tor[++rnum]=id[i]; }else { int now=query(q[id[i]].x2,q[id[i]].y2)-query(q[id[i]].x2,q[id[i]].y1-1)-query(q[id[i]].x1-1,q[id[i]].y2)+query(q[id[i]].x1-1,q[id[i]].y1-1); if (now>=q[id[i]].c) tol[++lnum]=id[i]; else q[id[i]].c-=now,tor[++rnum]=id[i]; } for (i=head;i<=tail;i++) if (q[id[i]].tg==1 && q[id[i]].c<=mid) change(q[id[i]].x1,q[id[i]].y1,-1); for (i=0;i<lnum;i++) id[head+i]=tol[i+1]; for (i=0;i<rnum;i++) id[head+i+lnum]=tor[i+1]; solve(head,head+lnum-1,l,mid); solve(head+lnum,tail,mid+1,r); } int main() { //freopen("a.in","r",stdin); //freopen("a.out","w",stdout); int i,j,x,t=0; // scanf("%d%d",&n,&m); n=read();m=read(); for (i=1;i<=n;i++) for (j=1;j<=n;j++) { id[++t]=t;x=read(); // scanf("%d",&x); q[t].x1=i;q[t].y1=j; q[t].c=x;q[t].tg=1; } for (i=1;i<=m;i++) { id[++t]=t; q[t].x1=read();q[t].y1=read(); q[t].x2=read();q[t].y2=read(); // scanf("%d%d%d%d",&q[t].x1,&q[t].y1,&q[t].x2,&q[t].y2); q[t].c=read();// scanf("%d",&q[t].c); q[t].tg=2;q[t].ans=-1; } solve(1,t,0,inf); for (i=1;i<=t;i++) if (q[i].tg==2) printf("%d\n",q[i].ans); return 0; }