zoukankan      html  css  js  c++  java
  • hdu 3648 Median Filter

    http://acm.hdu.edu.cn/showproblem.php?pid=3648

      题意相当简单,就是要找出所有给定大小的r*r的矩阵的中位数。

      这题理论上可以用各种各样的数据结构完成,可以用线段树(或线段树的退化版,点树),treap,AVL树,或者树状数组等。不过,由于数据规模的限制,这题就只能用树状数组来过了。因为其他以上提到的数据结构都是因为常数太大,所以会超时。另外,这题还要模拟矩阵移动的过程,要蛇形移动,否则元素进出树状数组的次数过多也会超时!

    AC精简版:

    View Code
      1 #include <cstdio>
      2 #include <cassert>
      3 #include <cstring>
      4 #include <algorithm>
      5 #include <cmath>
      6 
      7 using namespace std;
      8 
      9 #define lson l, m, rt << 1
     10 #define rson m + 1, r, rt << 1 | 1
     11 
     12 const int maxn = 1000005;
     13 int mp[501][501], out[500][500];
     14 
     15 void scan(int &a){
     16     char ch;
     17 
     18     while ((ch = getchar()) < '0' || ch > '9');
     19     a = ch - '0';
     20     while ((ch = getchar()) >= '0' && ch <= '9')
     21         a = a * 10 + ch - '0';
     22 }
     23 int C[maxn], Max;
     24 
     25 void add(int p){
     26     p++;
     27     while (p <= Max){
     28         C[p]++;
     29         p += p & (-p);
     30     }
     31 }
     32 
     33 void sub(int p){
     34     p++;
     35     while (p <= Max){
     36         C[p]--;
     37         p += p & (-p);
     38     }
     39 }
     40 
     41 int find(int k){
     42     int pos = 0, cnt = 0;
     43 
     44     k++;
     45     for(int i = 20; i >= 0; i--){
     46         pos += (1 << i);
     47         if (pos >= Max || cnt + C[pos] >= k) pos -= (1 << i);
     48         else cnt += C[pos];
     49     }
     50     return pos;
     51 }
     52 
     53 void deal(int n, int r){
     54     int len = r << 1 | 1;
     55     int end = n - len + 1;
     56     int pos = (len * len + 1) >> 1;
     57 
     58     Max = 0;
     59     for (int i = 0; i < n; i++){
     60         for (int j = 0; j < n; j++){
     61             scan(mp[i][j]);
     62             Max = max(Max, mp[i][j]);
     63         }
     64     }
     65     Max++;
     66     fill(C, C + Max + 1, 0);
     67 
     68     for (int i = 0, endi = len - 1; i < endi; i++){
     69         for (int j = 0; j < len; j++){
     70             add(mp[i][j]);
     71         }
     72     }
     73     for (int i = 0; i < end; i++){
     74         if (i & 1){
     75             for (int j = 0; j < len; j++){
     76                 add(mp[i + len - 1][j + end - 1]);
     77             }
     78             out[i][end - 1] = find(pos - 1);
     79             for (int j = end - 2; j >= 0; j--){
     80                 for (int k = 0; k < len; k++){
     81                     sub(mp[i + k][j + len]);
     82                     add(mp[i + k][j]);
     83                 }
     84                 out[i][j] = find(pos - 1);
     85             }
     86             for (int j = 0; j < len; j++){
     87                 sub(mp[i][j]);
     88             }
     89         }
     90         else{
     91             for (int j = 0; j < len; j++){
     92                 add(mp[i + len - 1][j]);
     93             }
     94             out[i][0] = find(pos - 1);
     95             for (int j = 1; j < end; j++){
     96                 for (int k = 0; k < len; k++){
     97                     sub(mp[i + k][j - 1]);
     98                     add(mp[i + k][j + len - 1]);
     99                 }
    100                 out[i][j] = find(pos - 1);
    101             }
    102             for (int j = 0; j < len; j++){
    103                 sub(mp[i][end + j - 1]);
    104             }
    105         }
    106     }
    107     for (int i = 0; i < end; i++){
    108         for (int j = 0; j < end; j++){
    109             printf("%d ", out[i][j]);
    110         }
    111         puts("");
    112     }
    113 }
    114 
    115 int main(){
    116     int n, m;
    117 
    118     while (~scanf("%d%d", &n, &m) && (n || m)){
    119         deal(n, m);
    120     }
    121 
    122     return 0;
    123 }

    原始版本(把线段树和树状数组都写进去了。。。。囧):

    View Code
      1 #include <cstdio>
      2 #include <cassert>
      3 #include <cstring>
      4 #include <algorithm>
      5 #include <cmath>
      6 
      7 using namespace std;
      8 
      9 #define lson l, m, rt << 1
     10 #define rson m + 1, r, rt << 1 | 1
     11 
     12 int mp[501][501], out[500][500];
     13 
     14 /*
     15 const int maxn = 1000005;
     16 int sum[maxn << 2];
     17 
     18 void up(int rt){
     19     sum[rt] = sum[rt << 1] + sum[rt << 1 | 1];
     20 }
     21 
     22 void update(int pos, int val, int l, int r, int rt){
     23     if (l == r){
     24         assert(l == pos);
     25         sum[rt] += val;
     26         return ;
     27     }
     28     if (!sum[rt] && (sum[rt << 1] || sum[rt << 1 | 1])) sum[rt << 1] = sum[rt << 1 | 1] = 0;
     29 
     30     int m = (l + r) >> 1;
     31 
     32     if (pos <= m) update(pos, val, lson);
     33     else update(pos, val, rson);
     34     up(rt);
     35 }
     36 
     37 int query(int k, int l, int r, int rt){
     38     if (l == r){
     39         return l;
     40     }
     41     int m = (l + r) >> 1;
     42 
     43     if (sum[rt << 1] >= k) return query(k, lson);
     44     else return query(k - sum[rt << 1], rson);
     45 }
     46 */
     47 
     48 void scan(int &a){
     49     char ch;
     50 
     51     while ((ch = getchar()) < '0' || ch > '9');
     52     a = ch - '0';
     53     while ((ch = getchar()) >= '0' && ch <= '9')
     54         a = a * 10 + ch - '0';
     55 }
     56 
     57 
     58 /*
     59 
     60 const int maxn = 1 << 20;
     61 int sum[maxn << 1], Max;
     62 
     63 void add(int n){
     64     int i = Max + n;
     65 
     66     for (++sum[i]; i > 1; i >>= 1){
     67         if (~i & 1){
     68             sum[i >> 1]++;
     69         }
     70     }
     71 }
     72 
     73 void sub(int n){
     74     if (!sum[n += Max]) return ;
     75     for (--sum[n]; n > 1; n >>= 1){
     76         if (~n & 1){
     77             --sum[n >> 1];
     78         }
     79     }
     80 }
     81 
     82 int find(int n){
     83     int i = 1;
     84 
     85     while (i < Max){
     86         if (n < sum[i]) i <<= 1;
     87         else n -= sum[i], i = i << 1 | 1;
     88     }
     89 
     90     return i - Max;
     91 }
     92 */
     93 
     94 const int maxn = 1000005;
     95 int C[maxn], Max;
     96 
     97 void add(int p){
     98     p++;
     99     while (p <= Max){
    100         C[p]++;
    101         p += p & (-p);
    102     }
    103 }
    104 
    105 void sub(int p){
    106     p++;
    107     while (p <= Max){
    108         C[p]--;
    109         p += p & (-p);
    110     }
    111 }
    112 
    113 int find(int k){
    114     int pos = 0, cnt = 0;
    115 
    116     k++;
    117     for(int i = 20; i >= 0; i--){
    118         pos += (1 << i);
    119         if (pos >= Max || cnt + C[pos] >= k) pos -= (1 << i);
    120         else cnt += C[pos];
    121     }
    122     return pos;
    123 }
    124 
    125 
    126 void deal(int n, int r){
    127     int len = r << 1 | 1;
    128     int end = n - len + 1;
    129     int pos = (len * len + 1) >> 1;
    130     //int maxSize = -1, minSize = maxn;
    131 
    132     Max = 0;
    133     //printf("len %d end %d pos %d\n", len, end, pos);
    134     for (int i = 0; i < n; i++){
    135         for (int j = 0; j < n; j++){
    136             scan(mp[i][j]);
    137             //scanf("%d", &mp[i][j]);
    138             Max = max(Max, mp[i][j]);
    139             //maxSize = max(mp[i][j], maxSize);
    140             //minSize = min(mp[i][j], minSize);
    141         }
    142     }
    143     Max++;
    144     fill(C, C + Max + 1, 0);
    145     /*
    146     if (Max){
    147         Max = 1 << (int)(log((double)Max) / log(2.0) + 1);
    148     }
    149     */
    150 
    151     //sum[1] = 0;
    152     for (int i = 0, endi = len - 1; i < endi; i++){
    153         for (int j = 0; j < len; j++){
    154             //printf("push %d %d\n", i, j);
    155             add(mp[i][j]);
    156             //update(mp[i][j], 1, minSize, maxSize, 1);
    157         }
    158     }
    159     for (int i = 0; i < end; i++){
    160         if (i & 1){
    161             for (int j = 0; j < len; j++){
    162                 //printf("push %d %d\n", i + len - 1, j + end - 1);
    163                 add(mp[i + len - 1][j + end - 1]);
    164                 //update(mp[i + len - 1][j + end - 1], 1, minSize, maxSize, 1);
    165             }
    166             out[i][end - 1] = find(pos - 1);
    167             //out[i][end - 1] = query(pos, minSize, maxSize, 1);
    168             for (int j = end - 2; j >= 0; j--){
    169                 for (int k = 0; k < len; k++){
    170                     //printf("pop %d %d\n", i + k, j + len);
    171                     sub(mp[i + k][j + len]);
    172                     //update(mp[i + k][j + len], -1, minSize, maxSize, 1);
    173                     //printf("push %d %d\n", i + k, j);
    174                     add(mp[i + k][j]);
    175                     //update(mp[i + k][j], 1, minSize, maxSize, 1);
    176                 }
    177                 out[i][j] = find(pos - 1);
    178                 //out[i][j] = query(pos, minSize, maxSize, 1);
    179             }
    180             for (int j = 0; j < len; j++){
    181                 //printf("pop %d %d\n", i, j);
    182                 sub(mp[i][j]);
    183                 //update(mp[i][j], -1, minSize, maxSize, 1);
    184             }
    185         }
    186         else{
    187             for (int j = 0; j < len; j++){
    188                 //printf("push %d %d\n", i + len - 1, j);
    189                 add(mp[i + len - 1][j]);
    190                 //update(mp[i + len - 1][j], 1, minSize, maxSize, 1);
    191             }
    192             out[i][0] = find(pos - 1);
    193             //out[i][0] = query(pos, minSize, maxSize, 1);
    194             for (int j = 1; j < end; j++){
    195                 for (int k = 0; k < len; k++){
    196                     //printf("pop %d %d\n", i + k, j - 1);
    197                     sub(mp[i + k][j - 1]);
    198                     //update(mp[i + k][j - 1], -1, minSize, maxSize, 1);
    199                     //printf("push %d %d\n", i + k, j + len - 1);
    200                     add(mp[i + k][j + len - 1]);
    201                     //update(mp[i + k][j + len - 1], 1, minSize, maxSize, 1);
    202                 }
    203                 out[i][j] = find(pos - 1);
    204                 //out[i][j] = query(pos, minSize, maxSize, 1);
    205             }
    206             for (int j = 0; j < len; j++){
    207                 //printf("pop %d %d\n", i, end + j - 1);
    208                 sub(mp[i][end + j - 1]);
    209                 //update(mp[i][end + j - 1], -1, minSize, maxSize, 1);
    210             }
    211         }
    212     }
    213     for (int i = 0; i < end; i++){
    214         for (int j = 0; j < end; j++){
    215             //if (j) putchar(' ');
    216             printf("%d ", out[i][j]);
    217         }
    218         puts("");
    219     }
    220 }
    221 
    222 int main(){
    223     int n, m;
    224 
    225     while (~scanf("%d%d", &n, &m) && (n || m)){
    226         deal(n, m);
    227     }
    228 
    229     return 0;
    230 }


    ——written by Lyon

  • 相关阅读:
    什么是递归神经网络
    2020年蜂窝网络连接超过110亿台设备
    伊朗Cisco路由器遭黑客攻击 全国互联网几乎瘫痪
    看了才知道!伊朗黑客组织原来这么牛
    美国知名Cloudflare网络公司遭中国顶尖黑客攻击
    如何对Web服务器进行飓风级防御
    美国的科技公司是如何使用加密的DNS
    揭秘网络黑客常见的6种必用攻击手段
    物联网是什么?您的家用电器从黑客手中安全吗
    不可不知!设置什么密码才不易被黑客破解
  • 原文地址:https://www.cnblogs.com/LyonLys/p/hdu_3648_Lyon.html
Copyright © 2011-2022 走看看