题目大意:给定n个整数,接下来有m个操作,操作分为两类,一类是修改操作:将第i个数改为k,另一类是查询操作:询问i,j之间第k大的数是多少。对于每个查询操作输出结果。
如果没有修改操作,可以直接用伴随数组来做。跟POJ2104那题一样。这里的关键是修改操作,如果每次修改后都进行排序的话,肯定挂掉,注意到我们这里每次只修改一个数,只需将修改的数排到正确的位置即可,可以使用链表实现。
这题的纠结之处在于数据格式,读入处理不好可能会WA或者RE。
View Code
1 #include <stdio.h> 2 #include <stdlib.h> 3 #define N 10010 4 #define INF 0x7fffffff 5 struct node 6 { 7 int x,id; 8 struct node *next; 9 }list[N]; 10 int cmp(const void* a,const void* b) 11 { 12 return ((struct node*)a)->x-((struct node*)b)->x; 13 } 14 int main() 15 { 16 int n,m,i,a,b,k,id; 17 char c; 18 struct node *p,*q; 19 while(~scanf("%d%d",&n,&m)) 20 { 21 for(i=1;i<=n;i++) 22 { 23 scanf("%d",&list[i].x); 24 list[i].id=i; 25 } 26 qsort(list+1,n,sizeof(list[0]),cmp); 27 for(i=0;i<=n;i++) list[i].next=&list[i+1]; 28 list[n+1].x=INF; 29 list[n+1].id=n+1; 30 list[n+1].next=0; 31 for(c=i=0;i<m;i++,c=0) 32 { 33 while(c!='Q'&&c!='C') scanf("%c",&c); 34 if(c=='Q') 35 { 36 scanf("%d%d%d",&a,&b,&k); 37 for(p=list;p->next;) 38 { 39 p=p->next; 40 id=p->id; 41 if(id>=a&&id<=b) k--; 42 if(!k) 43 { 44 printf("%d\n",p->x); 45 break; 46 } 47 } 48 } 49 else if(c=='C') 50 { 51 scanf("%d%d",&id,&k); 52 for(p=list;p->next;p=p->next) 53 { 54 if(p->next->id==id) 55 { 56 q=p->next; 57 q->x=k; 58 p->next=q->next; 59 break; 60 } 61 } 62 for(p=list;p->next;p=p->next) 63 { 64 if(p->next->x>=k) 65 { 66 q->next=p->next; 67 p->next=q; 68 break; 69 } 70 } 71 } 72 } 73 } 74 return 0; 75 }