记录编号 245548 评测结果 AAAAAAAAAA
题目名称 学数数 最终得分 100
用户昵称 GravatarFmuckss 是否通过 通过
代码语言 C++ 运行时间 0.804 s
提交时间 2016-04-03 17:47:31 内存使用 7.73 MiB
显示代码纯文本
  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstring>
  4. #include<algorithm>
  5. using namespace std;
  6. const int maxn = 1e5+10;
  7. typedef long long LL;
  8. inline int get_num(int &ans) {
  9. ans = 0;
  10. char tmp = getchar();
  11. while(tmp < '0' || tmp > '9') tmp = getchar();
  12. while(tmp <= '9' && tmp >= '0') {
  13. ans = ans*10 + tmp - '0';
  14. tmp = getchar();
  15. }
  16. }
  17. inline int get_num(int &ans, char &han) {
  18. ans = 0;
  19. char tmp = getchar();
  20. while(tmp < '0' || tmp > '9') {
  21. if(tmp == '=' || tmp == '<' || tmp == '>') han = tmp;
  22. tmp = getchar();
  23. }
  24. while(tmp <= '9' && tmp >= '0') {
  25. ans = ans*10 + tmp - '0';
  26. tmp = getchar();
  27. }
  28. }
  29. int v[maxn];//值
  30. int rank[maxn];//值的有序序列
  31. int tar[maxn];//值的位置
  32. int l[maxn];//左覆盖区间
  33. int r[maxn]; //右覆盖区间
  34. int n, q, cnt;
  35. LL cover[maxn];//覆盖范围
  36. LL psum[maxn], ssum[maxn];//前缀和,后缀和
  37.  
  38.  
  39. template <class T> class stack {
  40. private:
  41. T a[maxn];
  42. int top_;
  43. public:
  44. inline stack() { top_ = 0; }
  45. inline void push(T tar) { a[++top_] = tar; }
  46. inline void pop() { --top_; }
  47. inline T top() { return a[top_]; }
  48. inline bool nempty() { return top_; }
  49. inline void clear() { top_ = 0; }
  50. };
  51.  
  52.  
  53. inline void read() {
  54. get_num(n); get_num(q);
  55. for(int i = 1; i <= n; ++i) {
  56. get_num(v[i]);
  57. }
  58. memcpy(tar, v, (n+1) << 2);
  59. }
  60.  
  61. stack<int> s;
  62.  
  63. inline void handle() {
  64. sort(v+1, v+n+1);//排序
  65. for(int i = 1; i <= n; ++i) {//去重(为了方便离散化处理)
  66. if(v[i] == v[i-1]) continue;
  67. rank[++cnt] = v[i];
  68. }
  69. for(int i = 1; i <= n; ++i) {
  70. tar[i] = lower_bound(rank+1, rank+cnt+1, tar[i]) - rank;//排序后的rank值
  71. }
  72. for(int i = 1; i <= n; ++i) {//处理从当前位置起向右最多能覆盖到哪一位
  73. while(s.nempty() & tar[i] > tar[s.top()]) { r[s.top()] = i-1; s.pop(); }//如果当前的数大于栈顶,那说明栈顶最多覆盖到当前数的前一位
  74. s.push(i);
  75. }
  76. while(s.nempty()) { r[s.top()] = n; s.pop(); }//栈里剩下的元素都是能覆盖的n的
  77. for(int i = n; i >= 1; --i) {//处理从当前位置起向左最多能覆盖到哪一位
  78. while(s.nempty() & tar[i] >= tar[s.top()]) { l[s.top()] = i+1; s.pop(); }//如果当前的数大于栈顶,那说明栈顶最多覆盖到当前数的后一位
  79. s.push(i);
  80. }
  81. while(s.nempty()) { l[s.top()] = 1; s.pop(); }//栈里剩下的元素都是能覆盖的1的
  82. for(int i = 1; i <= n; i++) {//确定覆盖区间
  83. cover[tar[i]] += (LL)(i-l[i]+1) * (LL)(r[i]-i+1);//如果有重复,这里会一起加上
  84. }
  85. for(int i = 1; i <= cnt; i++) {
  86. psum[i] = psum[i-1]+cover[i];
  87. ssum[cnt-i+1] = ssum[cnt-i+2] + cover[cnt-i+1];
  88. }
  89. }
  90.  
  91. inline void sovle() {
  92. char han;
  93. int num;
  94. int pos;
  95. for(int i = 1; i <= q; ++i) {
  96. get_num(num, han);
  97. if(han == '=') {//直接找到对应cover中的位置输出即可
  98. pos = lower_bound(rank+1, rank+cnt+1, num) - rank; //找到要查询元素的位置
  99. if(rank[pos] != num) printf("0\n");//如果该元素在数组中并不存在
  100. else printf("%lld\n", cover[pos]);
  101. } else if(han == '<') {//需要要查询该数位置之前的所有的数(前缀和),这里去重的优势就体现出来啦~
  102. pos = lower_bound(rank+1, rank+cnt+1, num) - rank;//大于等于num
  103. printf("%lld\n", psum[pos-1]);//所以减一
  104. } else {//需要要查询该数位置之后的所有的数(后缀和)
  105. pos = upper_bound(rank+1, rank+cnt+1, num) - rank;//大于num
  106. printf("%lld\n", ssum[pos]);//已经满足
  107. }
  108. }
  109. }
  110. int main() {
  111. freopen("jxthree.in", "r", stdin);
  112. freopen("jxthree.out", "w", stdout);
  113. read();
  114. handle();
  115. sovle();
  116. return 0;
  117. }