又是一瓶奶,一道题,一写就是一小时。。。。思路蛮快的,链表删除反倒是出错看了半天我去。
我的思路:
我们不能一个一个机械地按照指令对数组进行排序操作。我们需要对操作序列预先处理,减少复杂度。由于处理过程需要进行增、删、遍历操作,我选择了链表作为数据结构。【不知道有没有更好的数据结构?】
首先说明一个命题:
操作为0是从前面降序,操作为1是从后面升序。假设操作0 m和1 n两次,则这俩操作区域在数组的示意图如下,阴影表示操作区域,要么:
|/m____n\\\\\\\\\\|
要么:
|nXXXm\\\\\\\|
第二种即有所交叉。
由于mn一个升序,一个降序,所以不管是先做m操作还是先做n操作,交叉的n___m段序列都一样。
以此为基础。
建立一个存储操作序列的链表。
typedef struct Link{
Link* next;
int p;
int q;
}Link;
typedef Link* List;
考虑操作数为0,操作下标假设为x。如果在已知的操作序列中,存在操作数为0、操作下标为y(y<x),我们认为0 x操作覆盖了0 y操作,将0 y从操作序列中删除。
此处覆盖指的是操作范围覆盖:
|XXXXXXy\\\\\\\\x________|
【注:这里能够轻易覆盖的原因就是我上面说的命题。】
同理,当操作数为1,操作下标假设为x。如果在已知的操作序列中,存在操作数为1、操作下标为y(y>x),我们认为0 x操作覆盖了0 y操作,将0 y从操作序列中删除。
最后再根据剩下的操作序列,对数组进行排序即可。
代码如下。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//链表的定义
typedef struct Link{
Link* next;
int p;
int q;
}Link;
typedef Link* List;
//链表节点创建函数
Link* CreateLinkNode(int p,int q){
Link* haha=(Link*)malloc(sizeof(Link));
haha->next=NULL;
haha->p=p;
haha->q=q;
return haha;
}
//链表添加元素
void AddList(List* list,int p,int q){
Link* node=CreateLinkNode(p,q);
if(*list==NULL){
*list=node;
return;
}
List point=*list;
while(point->next){
point=point->next;
}
point->next=node;
}
//删除特定元素
void DeleteList(List* list,int p,int q){
if(*list==NULL) return;
//删除头节点的情况要特殊考虑
while(((*list)->p==p)&&(((*list)->p==1&&(*list)->q>=q)||((*list)->p==0&&(*list)->q<=q))){
*list=(*list)->next;
if(*list==NULL) return;
}
//删除符合条件的一般节点
List point=(*list)->next;
List pre=*list;
while(point){
if((point->p==p)&&((point->p==1&&point->q>=q)||(point->p==0&&point->q<=q)))
{
pre->next=point->next;
point=pre->next;
}
pre=point;
if(point==NULL) break;
point=point->next;
}
}
//qsort的比较函数
int RisingCompare(const void*a,const void*b){
return *((int*)a)-*((int*)b);
}
int DecresingCompare(const void*a,const void*b){
return *((int*)b)-*((int*)a);
}
//清除掉前面重复无用的操作序列,并添加新的操作到操作序列
void DeterminWhetherToLeave(List* list,int p,int q){
DeleteList(list,p,q);
AddList(list,p,q);
}
int main(){
//初始化数组
int numsSize,operaCounts;
scanf("%d %d",&numsSize,&operaCounts);
int a[numsSize];
for(int i=0;i<numsSize;i++){
a[i]=i+1;
}
//管理添加操作序列
List list=NULL;
for(int i=0;i<operaCounts;i++){
int p,q;
scanf("%d %d",&p,&q);
DeterminWhetherToLeave(&list,p,q);
}
//按照操作序列进行排序
List point=list;
int *b=a;
while(point){
if(point->p==1){
qsort(b+point->q-1,numsSize-point->q+1,sizeof(int),RisingCompare);
}
else{
qsort(b,point->q,sizeof(int),DecresingCompare);
}
point=point->next;
}
//输出结果
for(int i=0;i<numsSize;i++){
printf("%d ",a[i]);
//TODO
}
}