司马称好
时间限制(普通/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 样例输出 3 题目来源 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;
}
*/