ZOJ Monthly, June 2012 - B Median - zoj 3612

最近好久没做比赛,加上考试什么的,压力很大。这几天休息,正好抽个空做下浙大月赛。发现自己果然变水了。

不过说起来,zju的月赛难度也在上升。

这是比赛时候做的第一题,题目是说每次会有 移除x 和 添加x 的操作,问你每次操作后,这串数组的中位数是什么。

操作n <= 10000

我的想法就是一共出现的数字最多就n个,可以把数据离散掉,然后用线段树,把操作更新掉,可以储存数组现有的数字个数ans。每次查找就查找(ans/2+1)个数字是啥就可以了,如果ans是偶数,再找ans/2个数字,两个相加/2

这题目唯一我的疑问就是为啥要LL。。。

怎么看数据不会爆啊,可是交了几次都wa了,我就一狠心改了LL交了一把...

View Code
  1 #include<cstdio>
  2 #include<iostream>
  3 #include<algorithm>
  4 #include<cstring>
  5 #include<cmath>
  6 #include<map>
  7 #include<vector>
  8 using namespace std;
  9 #define N 10010
 10 #define M 10010
 11 #define inf 2000000000
 12 typedef long long LL;
 13 map<LL, LL> id;
 14 map<LL, LL> fid;
 15 struct node {
 16     LL a, time;
 17     char str[7];
 18 }w[N];
 19 bool cmp1(const node &a, const node &b) {
 20     return a.a < b.a;
 21 }
 22 bool cmp2(const node &a, const node &b) {
 23     return a.time < b.time;
 24 }
 25 struct node1 {
 26     LL l, r, num;
 27 }tr[N*10];
 28 void build(LL L, LL R, LL x) {
 29     tr[x].l = L;
 30     tr[x].r = R;
 31     tr[x].num = 0;
 32     if (L == R) return ;
 33     LL mid = (L + R) / 2;
 34     build(L, mid, x*2);
 35     build(mid+1, R, x*2+1);
 36 }
 37 LL flag, ans, temp;
 38 void update(LL ii, LL x, LL f) {
 39     if (tr[x].l == tr[x].r) {
 40         if (!f) {
 41             if (!tr[x].num) flag = 1;
 42             else {
 43                 ans--;
 44                 tr[x].num--;
 45             }
 46         }
 47         else {
 48             ans++;
 49             tr[x].num++;
 50         }
 51         return ;
 52     }
 53     LL mid = (tr[x].l + tr[x].r) / 2;
 54     if (mid >= ii) update(ii, x*2, f);
 55     else update(ii, x*2+1, f);
 56     tr[x].num = tr[x*2].num + tr[x*2+1].num;
 57 }
 58 void find(LL ii, LL x) {
 59     if (tr[x].l == tr[x].r) {
 60         temp += fid[tr[x].r];
 61         return ;
 62     }
 63     if (tr[x*2].num >= ii) find(ii, x*2);
 64     else find(ii-tr[x*2].num, x*2+1);
 65 }
 66 int main() {
 67     LL T, n;
 68     scanf("%lld", &T);
 69     while (T--) {
 70         fid.clear();
 71         id.clear();
 72         scanf("%lld", &n);
 73         for(LL i = 0; i < n; ++i) {
 74             w[i].time = i;
 75             scanf("%s%lld", w[i].str, &w[i].a);
 76         }
 77         sort(w, w + n, cmp1);
 78         LL cs = 1;
 79         for (LL i = 0; i < n; ++i) {
 80             if (id.find(w[i].a) == id.end()) {
 81                 fid[cs] = w[i].a;
 82                 id[w[i].a] = cs++;
 83             }
 84         }
 85         build(1, cs-1, 1);
 86         sort(w, w + n, cmp2);
 87         ans = 0;
 88         for (LL i = 0; i < n; ++i) {
 89             LL ii = id[w[i].a];
 90             temp = flag = 0;
 91             if (w[i].str[0] == 'r') update(ii, 1, 0);
 92             else update(ii, 1, 1);
 93             if (flag) printf("Wrong!\n");
 94             else if(!ans) printf("Empty!\n");
 95             else {
 96                 find(ans/2+1, 1);
 97                 if (ans%2) printf("%lld\n", temp);
 98                 else {
 99                     find(ans/2, 1);
100                     if (temp%2 == 0) printf("%lld\n", temp/2);
101                     else printf("%.1f\n", double(temp)/2);
102                 }
103             }
104         }
105     }
106     return 0;
107 }

转载于:https://www.cnblogs.com/slon/archive/2012/06/30/2571039.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值