HDU 4941 Magical Forest (Hash)

这个题比赛的时候是乱搞的,比赛结束之后学长说是映射+hash才恍然大悟。因此决定好好学一下hash。

题意:

  M*N的格子,里面有一些格子里面有一个值。

  有三种操作:

    1.交换两行的值。

    2.交换两列的值。

    3.询问某个格子的值。

  保证,交换的时候要么两行都有值,要么两行都为空。

 

 思路:

  其实交换两行或者两列的话,相当于把那两行的对应下标交换一下。因此我们可以想到,对行标和列表建立一个索引,交换的时候,我们只需要交换一下索引。

  因为行和列比较多,所以我们不能直接存整个矩阵,即使离散化也不可以,所以这里我们需要用到hash。(Map也可以)。

 

代码:

  

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <cstdlib>
  5 #include <cmath>
  6 #include <algorithm>
  7 #include <string>
  8 #include <queue>
  9 #include <stack>
 10 #include <vector>
 11 #include <map>
 12 #include <set>
 13 #include <functional>
 14 #include <time.h>
 15 
 16 using namespace std;
 17 
 18 typedef __int64 ll;
 19 
 20 const int INF = 1<<30;
 21 const int MAXN = (int) 1e5+50;
 22 const ll HASH = (ll) (1e6)+3;
 23 
 24 struct node {
 25     int x, y, e;
 26 }a[MAXN];
 27 
 28 int hash_table[HASH], next[MAXN];
 29 
 30 int d_x[MAXN], d_y[MAXN], len_x, len_y;
 31 int xx[MAXN], yy[MAXN];
 32 int n;
 33 ll mx, my;
 34 
 35 inline void add(int x, int y, int k) {
 36     int id = ((ll)x*n+y)%HASH;
 37     next[k] = hash_table[id];
 38     hash_table[id] = k;
 39 }
 40 
 41 inline int find(int x, int y) {
 42     int id = ((ll)x*n+y)%HASH;
 43     int p;
 44     for (p = hash_table[id]; p!=-1; p = next[p])
 45         if (a[p].x==x&&a[p].y==y)
 46             return a[p].e;
 47     return 0;
 48 }
 49 
 50 void solve() {
 51     memset(hash_table, -1, sizeof(hash_table));
 52     scanf("%d%d%d", &mx, &my, &n);
 53     for (int i = 0; i < n; i++) {
 54         scanf("%d%d%d", &a[i].x, &a[i].y, &a[i].e);
 55         d_x[i] = a[i].x;
 56         d_y[i] = a[i].y;
 57         xx[i] = yy[i] = i;
 58     }
 59     sort(d_x, d_x+n);
 60     len_x = unique(d_x, d_x+n) - d_x;
 61     sort(d_y, d_y+n);
 62     len_y = unique(d_y, d_y+n) - d_y;
 63     for (int i = 0; i < n; i++) {
 64         a[i].x = lower_bound(d_x, d_x+len_x, a[i].x)-d_x;
 65         a[i].y = lower_bound(d_y, d_y+len_y, a[i].y)-d_y;
 66         add(a[i].x, a[i].y, i);
 67     }
 68 
 69     int Q, o, x, y;
 70     int rx, ry;
 71     scanf("%d", &Q);
 72     while (Q--) {
 73         scanf("%d%d%d", &o, &x, &y);
 74         if (o==1) {
 75             rx = lower_bound(d_x, d_x+len_x, x) - d_x;
 76             ry = lower_bound(d_x, d_x+len_x, y) - d_x;
 77             if (x==d_x[rx]&&y==d_x[ry]) swap(xx[rx], xx[ry]);
 78         } else if (o==2) {
 79             rx = lower_bound(d_y, d_y+len_y, x) - d_y;
 80             ry = lower_bound(d_y, d_y+len_y, y) - d_y;
 81             if (x==d_y[rx]&&y==d_y[ry]) swap(yy[rx], yy[ry]);
 82         } else {
 83             rx = lower_bound(d_x, d_x+len_x, x) - d_x;
 84             ry = lower_bound(d_y, d_y+len_y, y) - d_y;
 85             if (x==d_x[rx]&&y==d_y[ry]) printf("%d\n", find(xx[rx], yy[ry]));
 86             else puts("-1");
 87         }
 88     }
 89 }
 90 
 91 int main() {
 92     #ifdef Phantom01
 93         freopen("HDU4941.in", "r", stdin);
 94         freopen("my4941.txt", "w", stdout);
 95     #endif //Phantom01
 96 
 97     int T;
 98     scanf("%d", &T);
 99     for (int i = 1; i <= T; i++) {
100         printf("Case #%d:\n", i);
101         solve();
102     }
103 
104     return 0;
105 }
View Code

 

转载于:https://www.cnblogs.com/Phantom01/p/3913593.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值