Description

  给你一个N*N的矩阵,不用算矩阵乘法,但是每次询问一个子矩形的第K小数。

Input

  第一行两个数N,Q,表示矩阵大小和询问组数;
  接下来N行N列一共N*N个数,表示这个矩阵;
  再接下来Q行每行5个数描述一个询问:x1,y1,x2,y2,k表示找到以(x1,y1)为左上角、以(x2,y2)为右下角的子矩形中的第K小数。

Output

  对于每组询问输出第K小的数。

Sample Input

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

Sample Output

1
3

HINT

  矩阵中数字是109以内的非负整数;

  20%的数据:N<=100,Q<=1000;

  40%的数据:N<=300,Q<=10000;

  60%的数据:N<=400,Q<=30000;

  100%的数据:N<=500,Q<=60000。

解题思路:

整体二分思想非常浓。

将点权排序,二分mid时加入前mid个答案。

在二维树状数组上+1

最后二维树状数组查询前缀合就知道区间有多少个数。

最后统计答案就好了。

代码:

 #include<cstdio>
#include<cstring>
#include<algorithm>
struct data{
int i,j;
int val;
}d[];
struct que{
int px,py,qx,qy;
int no;
int val;
}q[],ss[],sp[];
int line[][];
int n,Q;
int cnt;
int top;
int ans[];
int lowbit(int x)
{
return x&(-x);
}
void update(int x,int y,int v)
{
for(int i=x;i<=n;i+=lowbit(i))
{
for(int j=y;j<=n;j+=lowbit(j))
{
line[i][j]+=v;
}
}
return ;
}
int query(int x,int y)
{
int ans=;
for(int i=x;i;i-=lowbit(i))
{
for(int j=y;j;j-=lowbit(j))
{
ans+=line[i][j];
}
}
return ans;
}
bool cmp(data x,data y)
{
return x.val<y.val;
}
void Insert(int no,int dir)
{
update(d[no].i,d[no].j,dir);
return ;
}
int sum(int no)
{
int ret=;
ret=query(q[no].qx,q[no].qy)+query(q[no].px-,q[no].py-);
ret-=query(q[no].qx,q[no].py-)+query(q[no].px-,q[no].qy);
return ret;
}
void macrs(int l,int r,int ll,int rr)
{
if(ll>rr)
return ;
if(l==r)
{
for(int i=ll;i<=rr;i++)
ans[q[i].no]=d[l].val;
return ;
}
int mid=(l+r)>>;
while(top<mid)
Insert(++top,);
while(top>mid)
Insert(top--,-);
int sta1=,sta2=;
for(int i=ll;i<=rr;i++)
{
if(sum(i)>=q[i].val)
sp[++sta1]=q[i];
else
ss[++sta2]=q[i];
}
int sta=ll-,lmid;
for(int i=;i<=sta1;i++)
q[++sta]=sp[i];
lmid=sta;
for(int i=;i<=sta2;i++)
q[++sta]=ss[i];
macrs(l,mid,ll,lmid);
macrs(mid+,r,lmid+,rr);
return ;
}
int main()
{
scanf("%d%d",&n,&Q);
for(int i=;i<=n;i++)
for(int j=;j<=n;j++)
{
int tmp;
scanf("%d",&tmp);
d[++cnt]=(data){i,j,tmp};
}
std::sort(d+,d+cnt+,cmp);
for(int i=;i<=Q;i++)
{
scanf("%d%d%d%d%d",&q[i].px,&q[i].py,&q[i].qx,&q[i].qy,&q[i].val);
if(q[i].px>q[i].qx)
std::swap(q[i].px,q[i].qx);
if(q[i].py>q[i].qy)
std::swap(q[i].py,q[i].qy);
q[i].no=i;
}
macrs(,cnt,,Q);
for(int i=;i<=Q;i++)
printf("%d\n",ans[i]);
return ;
}

最新文章

  1. npm源切换
  2. 网站内容禁止复制和粘贴、另存为的js代码(转)
  3. python(24)urlencode和urldecode
  4. JS --正则表达式验证、实战之邮箱模式
  5. samba的简单用法总结
  6. 简单设置 navgationbar(导航栏) 的 title 字体跟颜色
  7. sprint3(第十天)
  8. OD调试程序3
  9. VB的if和elseif
  10. 李洪强漫谈iOS开发[C语言-010] - C语言简要复习
  11. 【Spark学习】Apache Spark配置
  12. 报错java.net.SocketException: Software caused connection abort: recv failed 怎么办
  13. NET调用Java之100-Continue的坑
  14. POJ-3026 Borg Maze---BFS预处理+最小生成树
  15. Tomcat访问路径去掉发布项目的项目名称
  16. C#生成指定长度随机数
  17. Java运行时动态加载类之ClassLoader
  18. oracle创建新的用户 创建序列 并生成自动自增
  19. 数据输入——生成你需要的echart图(世界地图,气泡图)
  20. ztree使用系列三(ztree与springmvc+spring+mybatis整合实现增删改查)

热门文章

  1. 最简单的HTML5游戏——贪吃蛇
  2. .Net 安装aliyun-oss
  3. POJ 3275 两种做法
  4. .net开源CMS
  5. ThinkPad X260 UEFI安装 win7 64位 方法
  6. 学习推荐《精通Python网络爬虫:核心技术、框架与项目实战》中文PDF+源代码
  7. IDEA集成Python插件,SDK配置
  8. 解决spring-boot启动中碰到的问题:Cannot determine embedded database driver class for database type NONE(转)
  9. 【Cocos游戏实战】功夫小子第五课之帮助场景和选关功能的实现
  10. 获取个人借阅信息---图书馆client