现在的位置: 首页 > 综合 > 正文

SWUN 1165 – 司马称好

2012年11月27日 ⁄ 综合 ⁄ 共 4628字 ⁄ 字号 评论关闭


司马称好

时间限制(普通/Java) : 2000 MS/ 6000 MS          运行内存限制 : 65536 KByte
总提交 : 36            测试通过 : 6

描述

汉朝时期,司马徽从不说别人的短处,与人说话时,从来不问别人的好恶,都说好话。一个同乡来问他安否,他回答好。有一个说自己的儿子死了,他也说大好。妻子骂他缺德,别人死了儿子为什么还要说好,司马徽说:“你的话也太好了。”

 

                                                     ————成语《司马称好》的由来

 

CH=称好?

对于这个同音问题,霸气侧漏的CH感到无比的愤慨,于是他亲自出马,教导司马微,教他算法,希望他从算法中领悟出做人的道理。

 

CH的第一堂课是学习黑箱测试法:CH动态的给出若干个操作,操作种类如下,

 

GET:第一次执行GET时,返回黑箱中第1小的元素,第二次执行GET时,返回黑箱中第2小的元素,第三次执行GET时返回黑箱中第3小的元素,依此类推......

 

ADD(val):在黑箱中插入数值为val的元素

 

CHG(i,j):把第i次插入的元素更改为j

 

下面,展示的便是样例中的操作执行过程

  

操作                         第i小          黑箱中的元素                                              输出值

 

1 ADD(3)       0       3   

2 GET          1       3                                 3 

3 ADD(1)       1       1, 3   

4 GET          2       1, 3                              3 

5 ADD(-4)      2       -4, 1, 3   

6 ADD(2)       2       -4, 1, 2, 3   

7 ADD(8)       2       -4, 1, 2, 3, 8   

8 ADD(-1000)   2       -1000, -4, 1, 2, 3, 8   

9 GET          3       -1000, -4, 1, 2, 3, 8             1 

10 GET         4       -1000, -4, 1, 2, 3, 8             2 

11 ADD(2)      4       -1000, -4, 1, 2, 2, 3, 8
 
12 CHG(6,-500) 4       -500, -4, 1, 2, 2, 3, 8

输入

第一行为整数n,表示一共有n个操作,

接下来的n行,每行开头是一个字符串S,表示操作的类型:

若S为GET,则输出当前第i小的元素,

若S为ADD(val),表示黑箱中加入值为val的元素

若S为CHG(i,j),表示把第i次插入的元素更改为j

 

其中,0 < n <= 500000, val和j为int型,数据保证合法

 

输出

对于每个GET,输出当前第i小的元素值。

样例输入

12
ADD(3) 
GET 
ADD(1) 
GET 
ADD(-4) 
ADD(2) 
ADD(8) 
ADD(-1000) 
GET 
GET 
ADD(2) 
CHG(6,-500)

样例输出

3
3
1
2

题目来源

YB

 

题目地址:

http://218.194.91.48/acmhome/problemdetail.do?&method=showdetail&id=1165

 

很久之前做的题目,代码有点搓~~

 

但确实算是比较经典的题目了~~   适合刚学堆的童鞋练练手~~

 

做法很简单,建立两个堆。一个最大堆,一个最小堆。

 

显然,最大堆存的是前n小的数,最小堆存的是后m-n大的数(假设m是数字总数,n表示询问的次数)。

 

也就是说,最小堆内所有数都比最大堆内的所有数还要大。

 

比较麻烦的处理是,更改第i个输入时,需要找到已改变位置的原数新位置,所以需要双向记录路径。

 

容易错的是,两个堆内的数,有时需要相互传递。即有可能出现最大堆的堆顶比最小堆的堆顶还要大,因此需要两个堆顶互换位置。

 

 

#include<cstdio>
#include<iostream>
#include<algorithm>

using namespace std;

int cnt1=0,cnt2=0,cnt=0;

struct Mark{
    int gt,f;
}s1[600000],s2[600000],gt[600000];

void add1(int v){
    if(v==1) return;
    if(s1[v].f>=s1[v>>1].f) return ;
    swap(s1[v],s1[v>>1]);
    gt[s1[v].gt].gt=v;
    gt[s1[v>>1].gt].gt=v>>1;
    add1(v>>1);
}
void add2(int v){
    if(v==1) return;
    if(s2[v].f<=s2[v>>1].f) return ;
    swap(s2[v],s2[v>>1]);
    gt[s2[v].gt].gt=v;
    gt[s2[v>>1].gt].gt=v>>1;
    add2(v>>1);
}
void change1(int v){
    int l=v<<1;
    if(l<cnt1)
        if(s1[l].f>s1[l+1].f)    l++;
    if(l>cnt1) return;
    if(s1[l].f>=s1[v].f) return ;
    swap(s1[v],s1[l]);
    gt[s1[v].gt].gt=v;
    gt[s1[l].gt].gt=l;
    change1(l);
}
void change2(int v){
    int l=v<<1;
    if(l<cnt2)
        if(s2[l].f<s2[l+1].f)    l++;
    if(l>cnt2) return;
    if(s2[l].f<=s2[v].f) return ;
    swap(s2[v],s2[l]);
    gt[s2[v].gt].gt=v;
    gt[s2[l].gt].gt=l;
    change2(l);    
}

int main(){
//    freopen("01.in","r",stdin);
//    freopen("02.out","w",stdout);
    int n,i,t,val,flag=0;
    char str[40];
    scanf("%d",&n);
    while(n--){
        scanf("%s",str);
    //    puts(str);
        if(str[0]=='A'){
            val=0;
            if(str[4]=='-') i=5;
            else i=4;
            for(;str[i]!=')';i++){
                val*=10;
                val+=str[i]-'0';
            }
            if(str[4]=='-') val=0-val;
            cnt++;
            cnt1++;
            gt[cnt].gt=cnt1;
            gt[cnt].f=1;
            s1[cnt1].f=val;
            s1[cnt1].gt=cnt;
            add1(cnt1);
        }
        else if(str[0]=='G'){
            cnt2++;
            s2[cnt2]=s1[1];
            gt[s1[1].gt].f=2;
            gt[s1[1].gt].gt=cnt2;
            if(cnt1>1){
                s1[1]=s1[cnt1];
                gt[s1[cnt1].gt].gt=1;
                change1(1);
            }
            cnt1--;
            add2(cnt2);
            if(cnt1 && cnt2)
                while(s1[1].f<s2[1].f){
                    swap(s1[1],s2[1]);
                    gt[s1[1].gt].f=1;
                    gt[s2[1].gt].f=2;
                    change1(1);
                    change2(1);
                }
            printf("%d\n",s2[1].f);
        }
        else {
            t=0;
            val=0;
            for(i=4;str[i]!=',';i++){
                t*=10;
                t+=str[i]-'0';
            }
            flag=0;
            if(str[++i]=='-'){
                i++;
                flag=1;
            }
            for(;str[i]!=')';i++){
                val*=10;
                val+=str[i]-'0';
            }
            if(flag) val=0-val;
            if(gt[t].f==1){
                s1[gt[t].gt].f=val;
                change1(gt[t].gt);
                add1(gt[t].gt);
            }
            else{
                s2[gt[t].gt].f=val;
                change2(gt[t].gt);
                add2(gt[t].gt);
            }
        }
//        printf("--add:  %d   --max:   %d\n",cnt,cnt2);
//        printf("--s1:  ");for(i=1;i<=cnt1;i++)printf("%d ",s1[i].f);printf("\n");
//        printf("--s2:  ");for(i=1;i<=cnt2;i++)printf("%d ",s2[i].f);printf("\n");
    }
    return 0;
}

/*  随机 
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstdlib>

using namespace std;

int main(){
//    freopen("01.in","w",stdout);
    int t,n=10000,cnt=0,now=0;
    printf("10000\n");
    while(n--){
        t=rand()%3;
        if(t==0){
            if(now<cnt){
                now++;
                printf("GET\n");
            }
            else t=1;
        }
        if(t==1){
            if(cnt==0) t=2;
            else printf("CHG(%d,%d)\n",rand()%cnt+1,rand()%2000-1000);
            
        }
        if(t==2){
            cnt++;
            printf("ADD(%d)\n",rand()%2000-1000);
        }
    }
    return 0;
}


*/


/*   暴力 

#include<cstdio>
#include<iostream>
#include<algorithm>

using namespace std;

int cnt=0,s[1000000],num=0,s1[1000000];
int main(){
//    freopen("01.in","r",stdin);
//    freopen("01.out","w",stdout);
    int n,i,t,val,flag=0;
    char str[40];
    scanf("%d",&n);
    while(n--){
        scanf("%s",str);

        if(str[0]=='A'){
            val=0;
            if(str[4]=='-') i=5;
            else i=4;
            for(;str[i]!=')';i++){
                val*=10;
                val+=str[i]-'0';
            }
            if(str[4]=='-') val=0-val;
            s[cnt++]=val;
        }
        else if(str[0]=='G'){
            for(i=0;i<cnt;i++)
                s1[i]=s[i];
            sort(s1,s1+cnt);
            printf("%d\n",s1[num++]);
        }
        else {
            t=0;
            val=0;
            for(i=4;str[i]!=',';i++){
                t*=10;
                t+=str[i]-'0';
            }
            flag=0;
            if(str[++i]=='-'){
                i++;
                flag=1;
            }
            for(;str[i]!=')';i++){
                val*=10;
                val+=str[i]-'0';
            }
            if(flag) val=0-val;
            s[t-1]=val;
        }

    }
    return 0;
}
*/ 

 

 

 

 

抱歉!评论已关闭.