题意就是有大约1-10000个操作,每次插入或者删除一个数,每次操作后的中位数都要输出
然后思路就比较清晰了, 先把数据都读进来,所有的数存起来离散化,然后再处理每个操作,每次维护树状数组即可,然后如果整个序列有奇数个,就直接二分找最中间的,如果偶数个就找两个数。
这题比较恶心的就是输出了。用cout按理说最好了,但是会超时,用long long的话,除以2的时候判奇数输出.5也会挂,除非转换成double然后%.1f不会挂,这一点很费解啊。当然直接用double转化为字符串是不可能挂的。
保险点用double 吧
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#define MAXN 10005
#define MAXM 1000005
#define INF 1000000000
#define eps 1e-6
using namespace std;
int op[MAXN];
int n, a[MAXN], t[MAXN];
double x[MAXN], num[MAXN];
int lowbit(int x)
{
return x & -x;
}
void modify(int x, int v)
{
for(int i = x; i <= n; i += lowbit(i))
a[i] += v;
}
int getsum(int x)
{
int sum = 0;
for(int i = x; i > 0; i -= lowbit(i))
sum += a[i];
return sum;
}
int find(double val, int low, int high)
{
while(low <= high)
{
int mid = (low + high) >> 1;
if(fabs(x[mid] - val) < eps) return mid;
if(x[mid] > val) high = mid - 1;
else low = mid + 1;
}
return -1;
}
int median(int val, int low, int high)
{
while(low <= high)
{
int mid = (low + high) >> 1;
int sum = getsum(mid);
if(sum >= val) high = mid - 1;
else low = mid + 1;
}
return low;
}
void output(double val)
{
if(floor(val) == val)
printf("%.0f\n", val);
else
{
char s[55];
sprintf(s, "%f", val);
int len = strlen(s);
int pos = len - 1;
for(int i = len - 1; i >= 0; i--)
{
if(s[i] != '0' || i == 0)
{
pos = i;
break;
}
}
for(int i = 0; i <= pos; i++) putchar(s[i]);
putchar('\n');
}
}
int main()
{
int T;
char s[22];
scanf("%d", &T);
while(T--)
{
scanf("%d", &n);
for(int i = 1; i <= n; i++)
{
scanf("%s%lf", s, &num[i]);
if(s[0] == 'r') op[i] = 0;
else op[i] = 1;
x[i] = num[i];
}
sort(x + 1, x + n + 1);
int f = n;
n = unique(x + 1, x + n + 1) - x - 1;
memset(a, 0, sizeof(a));
memset(t, 0, sizeof(t));
for(int i = 1; i <= f; i++)
{
if(op[i])
{
int pos = find(num[i], 1, n);
modify(pos, 1);
t[pos]++;
int len = getsum(n);
if(len % 2 == 1)
{
double k = x[median(len / 2 + 1, 1, n)];
output(k);
}
else
{
double k1 = x[median(len / 2, 1, n)];
double k2 = x[median(len / 2 + 1, 1, n)];
output((k1 + k2) / 2);
}
}
else
{
int pos = find(num[i], 1, n);
if(t[pos] < 1) printf("Wrong!\n");
else
{
t[pos]--;
modify(pos, -1);
int len = getsum(n);
if(len == 0) printf("Empty!\n");
else if(len % 2 == 1)
{
double k = x[median(len / 2 + 1, 1, n)];
output(k);
}
else
{
double k1 = x[median(len / 2, 1, n)];
double k2 = x[median(len / 2 + 1, 1, n)];
output((k1 + k2) / 2);
}
}
}
}
}
return 0;
}