记录编号 |
245548 |
评测结果 |
AAAAAAAAAA |
题目名称 |
学数数 |
最终得分 |
100 |
用户昵称 |
Fmuckss |
是否通过 |
通过 |
代码语言 |
C++ |
运行时间 |
0.804 s |
提交时间 |
2016-04-03 17:47:31 |
内存使用 |
7.73 MiB |
显示代码纯文本
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 1e5+10;
typedef long long LL;
inline int get_num(int &ans) {
ans = 0;
char tmp = getchar();
while(tmp < '0' || tmp > '9') tmp = getchar();
while(tmp <= '9' && tmp >= '0') {
ans = ans*10 + tmp - '0';
tmp = getchar();
}
}
inline int get_num(int &ans, char &han) {
ans = 0;
char tmp = getchar();
while(tmp < '0' || tmp > '9') {
if(tmp == '=' || tmp == '<' || tmp == '>') han = tmp;
tmp = getchar();
}
while(tmp <= '9' && tmp >= '0') {
ans = ans*10 + tmp - '0';
tmp = getchar();
}
}
int v[maxn];//值
int rank[maxn];//值的有序序列
int tar[maxn];//值的位置
int l[maxn];//左覆盖区间
int r[maxn]; //右覆盖区间
int n, q, cnt;
LL cover[maxn];//覆盖范围
LL psum[maxn], ssum[maxn];//前缀和,后缀和
template <class T> class stack {
private:
T a[maxn];
int top_;
public:
inline stack() { top_ = 0; }
inline void push(T tar) { a[++top_] = tar; }
inline void pop() { --top_; }
inline T top() { return a[top_]; }
inline bool nempty() { return top_; }
inline void clear() { top_ = 0; }
};
inline void read() {
get_num(n); get_num(q);
for(int i = 1; i <= n; ++i) {
get_num(v[i]);
}
memcpy(tar, v, (n+1) << 2);
}
stack<int> s;
inline void handle() {
sort(v+1, v+n+1);//排序
for(int i = 1; i <= n; ++i) {//去重(为了方便离散化处理)
if(v[i] == v[i-1]) continue;
rank[++cnt] = v[i];
}
for(int i = 1; i <= n; ++i) {
tar[i] = lower_bound(rank+1, rank+cnt+1, tar[i]) - rank;//排序后的rank值
}
for(int i = 1; i <= n; ++i) {//处理从当前位置起向右最多能覆盖到哪一位
while(s.nempty() & tar[i] > tar[s.top()]) { r[s.top()] = i-1; s.pop(); }//如果当前的数大于栈顶,那说明栈顶最多覆盖到当前数的前一位
s.push(i);
}
while(s.nempty()) { r[s.top()] = n; s.pop(); }//栈里剩下的元素都是能覆盖的n的
for(int i = n; i >= 1; --i) {//处理从当前位置起向左最多能覆盖到哪一位
while(s.nempty() & tar[i] >= tar[s.top()]) { l[s.top()] = i+1; s.pop(); }//如果当前的数大于栈顶,那说明栈顶最多覆盖到当前数的后一位
s.push(i);
}
while(s.nempty()) { l[s.top()] = 1; s.pop(); }//栈里剩下的元素都是能覆盖的1的
for(int i = 1; i <= n; i++) {//确定覆盖区间
cover[tar[i]] += (LL)(i-l[i]+1) * (LL)(r[i]-i+1);//如果有重复,这里会一起加上
}
for(int i = 1; i <= cnt; i++) {
psum[i] = psum[i-1]+cover[i];
ssum[cnt-i+1] = ssum[cnt-i+2] + cover[cnt-i+1];
}
}
inline void sovle() {
char han;
int num;
int pos;
for(int i = 1; i <= q; ++i) {
get_num(num, han);
if(han == '=') {//直接找到对应cover中的位置输出即可
pos = lower_bound(rank+1, rank+cnt+1, num) - rank; //找到要查询元素的位置
if(rank[pos] != num) printf("0\n");//如果该元素在数组中并不存在
else printf("%lld\n", cover[pos]);
} else if(han == '<') {//需要要查询该数位置之前的所有的数(前缀和),这里去重的优势就体现出来啦~
pos = lower_bound(rank+1, rank+cnt+1, num) - rank;//大于等于num
printf("%lld\n", psum[pos-1]);//所以减一
} else {//需要要查询该数位置之后的所有的数(后缀和)
pos = upper_bound(rank+1, rank+cnt+1, num) - rank;//大于num
printf("%lld\n", ssum[pos]);//已经满足
}
}
}
int main() {
freopen("jxthree.in", "r", stdin);
freopen("jxthree.out", "w", stdout);
read();
handle();
sovle();
return 0;
}