• 【清澄A1333】【整体二分+二维树状数组】矩阵乘法(梁盾)


    试题来源
      2012中国国家集训队命题答辩
    问题描述
      给你一个N*N的矩阵,不用算矩阵乘法,但是每次询问一个子矩形的第K小数。
    输入格式
      第一行两个数N,Q,表示矩阵大小和询问组数;
      接下来N行N列一共N*N个数,表示这个矩阵;
      再接下来Q行每行5个数描述一个询问:x1,y1,x2,y2,k表示找到以(x1,y1)为左上角、以(x2,y2)为右下角的子矩形中的第K小数。
    输出格式
      对于每组询问输出第K小的数。
    样例输入
    2 2
    2 1
    3 4
    1 2 1 2 1
    1 1 2 2 3
    样例输出
    1
    3
    数据规模和约定
      矩阵中数字是109以内的非负整数;
      20%的数据:N<=100,Q<=1000;
      40%的数据:N<=300,Q<=10000;
      60%的数据:N<=400,Q<=30000;
      100%的数据:N<=500,Q<=60000。
    【分析】
    其实用可持久化的线段树应该也可以做。
    裸的整体二分题,把每个输入的点按权值排个序就可以了。
    其实可以加一点修改什么的,这样加着修改一起二分难度稍微大一点。
    本周在校最后一题,哈哈哈..
      1 /*
      2 李商隐
      3 《无题·重帏深下莫愁堂》
      4 重帏深下莫愁堂,卧后清宵细细长。
      5 神女生涯原是梦,小姑居处本无郎。
      6 风波不信菱枝弱,月露谁教桂叶香。
      7 直道相思了无益,未妨惆怅是清狂。
      8 */
      9 #include <iostream>
     10 #include <cstdio>
     11 #include <algorithm>
     12 #include <cstring>
     13 #include <vector>
     14 #include <utility>
     15 #include <iomanip>
     16 #include <string>
     17 #include <cmath>
     18 #include <queue>
     19 #include <assert.h>
     20 #include <map>
     21 #include <ctime>
     22 #include <cstdlib>
     23 #include <stack>
     24 #define LOCAL
     25 const int MAXN = 500 + 10;
     26 const int MAXM = 60000 + 10;
     27 const int INF = 1000000000;
     28 const int SIZE = 450;
     29 const int maxnode =  250005 + 10;
     30 using namespace std;
     31 typedef long long ll;
     32 using namespace std;
     33 int n, m, cnt;
     34 int pos, Maxv;
     35 int c[MAXN][MAXN], Ans[MAXM];
     36 int id[MAXM];
     37 int tmp[MAXM];
     38 bool mark[MAXM];
     39 
     40 struct DATA{
     41     //横纵坐标和值 
     42     int x, y, val;
     43     bool operator < (const DATA &b)const {
     44          return val < b.val;
     45     }
     46 }data[maxnode];
     47 //问题 
     48 struct QUESTION{
     49     int x1, x2;
     50     int y1, y2, K;
     51 }q[MAXM];
     52 //输入 
     53 
     54 inline int lowbit(int x){return x & -x;}
     55 //插入 
     56 void add(int x, int y, int val){
     57     int f = y;
     58     while (x <= n){
     59           while (y <= n){
     60                 c[x][y] += val;
     61                 y += lowbit(y);
     62           }
     63           y = f;
     64           x += lowbit(x);
     65     } 
     66     return;
     67 }
     68 int sum(int x, int y){//
     69     int tmp = 0, f = y;
     70     while (x > 0){
     71           while (y > 0){
     72                 tmp += c[x][y];
     73                 y -= lowbit(y);
     74           }
     75           y = f;
     76           x -= lowbit(x);
     77     }
     78     return tmp;
     79 }
     80 //查询 
     81 int query(int k){
     82     int x1, x2, y1, y2;
     83     x1 = q[k].x1;x2 = q[k].x2;
     84     y1 = q[k].y1;y2 = q[k].y2;
     85     return sum(x2, y2) + sum(x1 - 1, y1 - 1) - sum(x1 - 1, y2) - sum(x2, y1 - 1);
     86 }
     87 //整体二分 
     88 void solve(int l, int r, int L, int R){
     89      if (l > r || L == R) return;//l和r是问题的编号 
     90      int mid = (L + R) >> 1;
     91      
     92      while (data[pos + 1].val <= mid && pos < cnt){//直接模拟 
     93            add(data[pos + 1].x, data[pos + 1].y, 1);
     94            pos++;
     95      }
     96      while (data[pos].val > mid){
     97            add(data[pos].x, data[pos].y , -1);
     98            pos--;
     99      }
    100      int cnt = 0;
    101      for (int i = l; i <= r; i++){
    102          if (query(id[i]) > q[id[i]].K - 1){
    103             mark[i] = 1;
    104             Ans[id[i]] = mid;
    105             cnt++;
    106          }else mark[i] = 0;
    107      } 
    108      int l1 = l, l2 = l + cnt;
    109      for (int i = l; i <= r; i++)
    110      if (mark[i]) tmp[l1++] = id[i];
    111      else tmp[l2++] = id[i];
    112      //分成两部分继续整体二分 
    113      for (int i = l; i <= r; i++) id[i] = tmp[i];
    114      solve(l, l1 - 1, L, mid);
    115      solve(l1, l2 - 1, mid + 1, R);
    116 }
    117 
    118 void init(){
    119     memset(mark, 0, sizeof(mark));
    120     memset(c, 0, sizeof(c));
    121     scanf("%d%d", &n, &m);
    122     Maxv = 0;
    123     cnt = 0;
    124     for (int i = 1; i <= n; i++)
    125     for (int j = 1; j <= n; j++){
    126         scanf("%d", &data[++cnt].val);
    127         data[cnt].x = i;//横纵坐标 
    128         data[cnt].y = j;
    129         Maxv = max(data[cnt].val, Maxv);
    130     }
    131     sort(data + 1, data + 1 + cnt); 
    132 }
    133 void work(){
    134      for (int i = 1; i <= m; i++){
    135          scanf("%d%d%d%d%d", &q[i].x1, &q[i].y1, &q[i].x2, &q[i].y2, &q[i].K);
    136      }
    137      for (int i = 1; i <= m; i++) id[i] = i;//问题序列
    138      solve(1, m, 0, Maxv + 1);
    139      for (int i = 1; i <= m; i++) printf("%d
    ", Ans[i]); 
    140 }
    141 
    142 int main(){
    143     
    144     init();
    145     work();
    146     return 0;
    147 }
    View Code
  • 相关阅读:
    TOC 1. TODO springboot优雅关机
    SpringBoot实现优雅的关机
    Spring Boot 内嵌容器 Tomcat / Undertow / Jetty 优雅停机实现
    正确、安全地停止SpringBoot应用服务
    springboot优雅关机
    简单几步教你实现移动硬盘PE、装win7/vista! 一盘在手,系统无忧!
    设置vista和win7进入Debug模式
    杀毒绝招:用“记事本” 处理顽固程序(命令行修改默认打开方式)
    win7 UAC bypass(微软已经给予了三组组件绕过UAC启动的特权)
    Win7,Vista UAC下应用程序标注为“需要管理员权限”的四种方法(可以修改注册表)
  • 原文地址:https://www.cnblogs.com/hoskey/p/4337826.html
Copyright © 2020-2023  润新知