[HDU 4666]Hyperspace[最远曼哈顿距离][STL]

题意:

许多 k 维点, 求这些点之间的最远曼哈顿距离. 并且有 q 次操作, 插入一个点或者删除一个点. 每次操作之后均输出结果.

思路:

用"疑似绝对值"的思想, 维护每种状态下各点的计算值, 插入或删除一个点就更新一次每种状态(用 multiset 或 map 或 priority_queue 实现), 每次求ans时扫一遍最大差值即可.


为了练习STL, 每一个都实现一次.


multiset

 

  1. /* **********************************************
  2. Author : kuangbin
  3. Created Time: 2013/8/13 18:25:38
  4. File Name : F:\2013ACM练习\2013多校7\1001.cpp
  5. *********************************************** */
  6. //4640MS    14972K
  7. #include <cstdio>
  8. #include <algorithm>
  9. #include <set>
  10. using namespace std;
  11. int a[60010][10];
  12. multiset<int>mst[1<<5];
  13. int main()
  14. {
  15. //freopen("in.txt","r",stdin);
  16. //freopen("out.txt","w",stdout);
  17. int q,k;
  18. while(scanf("%d%d",&q,&k)==2)
  19. {
  20. for(int i = 0;i < (1<<k);i++)
  21. mst[i].clear();
  22. int od,x;
  23. for(int i = 1;i <= q;i++)
  24. {
  25. scanf("%d",&od);
  26. if(od == 0)
  27. {
  28. for(int j = 0;j < k;j++)
  29. scanf("%d",&a[i][j]);
  30. for(int j = 0; j < (1<<k); j++)
  31. {//计算当前点在每种情况下的"疑似绝对值"
  32. int s = 0;
  33. for(int t = 0; t < k;t++)
  34. if(j & (1<<t))
  35. s += a[i][t];
  36. else s -= a[i][t];
  37. mst[j].insert(s);//插入到该种情况下
  38. }
  39. }
  40. else
  41. {
  42. scanf("%d",&x);
  43. for(int j = 0; j < (1<<k); j++)
  44. {//一次操作,插入或删除一个点,都是将这个点对应的所有状态插入每种状态中
  45. int s = 0;//因此,要清除一次操作,就要删除所有状态中的那一个
  46. for(int t = 0; t < k;t++)
  47. if(j & (1<<t))
  48. s += a[x][t];
  49. else s -= a[x][t];
  50. multiset<int>::iterator it = mst[j].find(s);
  51. mst[j].erase(it);
  52. }
  53. }
  54. int ans = 0;
  55. for(int j = 0; j < (1<<k);j++)
  56. {
  57. multiset<int>::iterator it = mst[j].end();
  58. it--;
  59. int t1 = (*it);
  60. it = mst[j].begin();
  61. int t2 = (*it);//用于作差
  62. ans = max(ans,t1-t2);//保留最大值
  63. }
  64. printf("%d\n",ans);
  65. }
  66. }
  67. return 0;
  68. }

 

map

 

  1. //8359MS 37928K慢死了
  2. #include <cstdio>
  3. #include <algorithm>
  4. #include <map>
  5. using namespace std;
  6. int a[60010][6];
  7. map<int, int> mp[1<<5];
  8. int main()
  9. {
  10. int q,k;
  11. while(scanf("%d %d",&q,&k)==2)
  12. {
  13. for(int i=0;i<1<<k;i++)
  14. mp[i].clear();
  15. int od, x;
  16. for(int i=1;i<=q;i++)
  17. {
  18. scanf("%d",&od);
  19. if(!od)
  20. {
  21. for(int j=0;j<k;j++)
  22. scanf("%d",a[i]+j);
  23. for(int s=0;s<1<<k;s++)
  24. {
  25. int t = 0;
  26. for(int j=0;j<k;j++)
  27. {
  28. if(s & (1<<j)) t += a[i][j];
  29. else t -= a[i][j];
  30. }
  31. mp[s][t]++;
  32. // printf("map[s][t] = %d\n",mp[s][t]);
  33. }
  34. }
  35. else
  36. {
  37. scanf("%d",&x);
  38. for(int s=0;s<1<<k;s++)
  39. {
  40. int t = 0;
  41. for(int j=0;j<k;j++)
  42. {
  43. if(s & (1<<j)) t += a[x][j];
  44. else t -= a[x][j];
  45. }
  46. map<int, int>::iterator it = mp[s].find(t);
  47. mp[s][t]--;
  48. }
  49. }
  50. int ans = 0;
  51. for(int s=0;s<(1<<k);s++)
  52. {
  53. map<int, int>::iterator it = mp[s].end();
  54. it--;
  55. while(it->second==0) it--;
  56. int mx = it->first;///first~~~
  57. it = mp[s].begin();
  58. while(it->second==0) it++;
  59. int mi = it->first;
  60. ans = max(ans, mx - mi);
  61. // printf("mx = %d, mi = %d\n",mx,mi);
  62. }
  63. printf("%d\n",ans);
  64. }
  65. }
  66. }

 

priority_queue

优先队列只能返回队首元素,因此需要两个队列分别求最大最小值.

对于已删除的元素, 无法直接删除, 可以做标记, 碰到已删除的元素时直接pop掉就行了.

因此入队的就不能仅仅是一个值(前两个有find功能, 不需要额外标号), 而应该是一个记录key和value的结构体.

 

  1. //2218MS 36748K
  2. #include <cstring>
  3. #include <cstdio>
  4. #include <algorithm>
  5. #include <queue>
  6. using namespace std;
  7. int a[6];
  8. bool vis[60005];
  9. typedef struct ascending_node
  10. {
  11. int id,t;
  12. bool operator<(const ascending_node& a) const
  13. {
  14. return t > a.t;
  15. }
  16. }anode;
  17. typedef struct descending_node
  18. {
  19. int id,t;
  20. bool operator<(const descending_node& a) const
  21. {
  22. return t < a.t;
  23. }
  24. }dnode;
  25. /* 2812MS 30224K
  26. priority_queue<anode> apq[1<<5];
  27. priority_queue<dnode> dpq[1<<5];
  28. int main()
  29. {
  30. int q,k;
  31. while(scanf("%d %d",&q,&k)==2)
  32. {
  33. for(int i=0;i<1<<k;i++)
  34. {
  35. while(!apq[i].empty()) apq[i].pop();
  36. while(!dpq[i].empty()) dpq[i].pop();
  37. }*/
  38. /**/
  39. int main()
  40. {
  41. int q,k;
  42. while(scanf("%d %d",&q,&k)==2)
  43. {
  44. priority_queue<anode> apq[1<<5];
  45. priority_queue<dnode> dpq[1<<5];/**/
  46. anode t1;
  47. dnode t2;
  48. memset(vis,false,sizeof(vis));
  49. int od, x;
  50. for(int i=1;i<=q;i++)
  51. {
  52. scanf("%d",&od);
  53. if(!od)
  54. {
  55. for(int j=0;j<k;j++)
  56. scanf("%d",a+j);
  57. for(int s=0;s<1<<k;s++)
  58. {
  59. int t = 0;
  60. for(int j=0;j<k;j++)
  61. {
  62. if(s & (1<<j)) t += a[j];
  63. else t -= a[j];
  64. }
  65. t1.t = t2.t = t;
  66. t1.id = t2.id = i;
  67. apq[s].push(t1);
  68. dpq[s].push(t2);
  69. // printf("map[s][t] = %d\n",mp[s][t]);
  70. }
  71. }
  72. else
  73. {
  74. scanf("%d",&x);
  75. vis[x] = true;
  76. }
  77. int ans = 0;
  78. for(int s=0;s<(1<<k);s++)
  79. {
  80. while(1)
  81. {
  82. t1 = apq[s].top();
  83. if(!vis[t1.id]) break;
  84. apq[s].pop();
  85. }
  86. while(1)
  87. {
  88. t2 = dpq[s].top();
  89. if(!vis[t2.id]) break;
  90. dpq[s].pop();
  91. }
  92. ans = max(ans, t2.t-t1.t);
  93. }
  94. printf("%d\n",ans);
  95. }
  96. }
  97. }


 

 

转载于:https://www.cnblogs.com/james1207/p/3293807.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值

举报

选择你想要举报的内容(必选)
  • 内容涉黄
  • 政治相关
  • 内容抄袭
  • 涉嫌广告
  • 内容侵权
  • 侮辱谩骂
  • 样式问题
  • 其他
点击体验
DeepSeekR1满血版
程序员都在用的中文IT技术交流社区

程序员都在用的中文IT技术交流社区

专业的中文 IT 技术社区,与千万技术人共成长

专业的中文 IT 技术社区,与千万技术人共成长

关注【CSDN】视频号,行业资讯、技术分享精彩不断,直播好礼送不停!

关注【CSDN】视频号,行业资讯、技术分享精彩不断,直播好礼送不停!

客服 返回顶部

登录后您可以享受以下权益:

×