洛谷P4305 [JLOI2011]不重复数字

题目链接:https://www.luogu.com.cn/problem/P4305

题目描述
给定 n 个数,要求把其中重复的去掉,只保留第一次出现的数。

输入格式
本题有多组数据。

第一行一个整数 T ,表示数据组数。

对于每组数据:

第一行一个整数 n 。

第二行 n 个数,表示给定的数。

输出格式
对于每组数据,输出一行,为去重后剩下的数,两个数之间用一个空格隔开。

输入输出样例
输入 #1
2
11
1 2 18 3 3 19 2 3 6 5 4
6
1 2 3 4 5 6
输出 #1
1 2 18 3 19 6 5 4
1 2 3 4 5 6

对于这道题,可以先让s[i]表示第i个数个值,定义结构体a[i].s=s[i],a[i].h=i,处理完之后a[i].s=s[a[i].h],之后对a[i].s进行归并排序,

排序之后循环如果a[i].h=a[i-1].h就说明a[i]是重复的,即s[a[i].h]不输出,就将a[i].h打上标记(flag[a[i].h]),

最后将没有标记的s[i]输出。

代码:

#include<stdio.h>
int t,n,s[50001],flag[50001];
struct node{
    int s,h;
}a[50001],r[50001];
int read(){
    int x=0,f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9'){
        if(ch=='-')
            f=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9'){
        x=(x<<1)+(x<<3)+(ch^48);
        ch=getchar();
    }
    return x*f;
}
void px(int s,int t){
    if(s==t)return;
    int mid=(s+t)>>1;
    px(s,mid);px(mid+1,t);
    int i=s,j=mid+1,k=s;
    while(i<=mid&&j<=t)
        if(a[i].s<=a[j].s)r[k++]=a[i++];
        else r[k++]=a[j++];
    while(i<=mid)r[k++]=a[i++];
    while(j<=t)r[k++]=a[j++];
    for(i=s;i<=t;i++)a[i]=r[i];
    return;
}
int main(){
    t=read();
    while(t--){
        n=read();
        for(int i=1;i<=n;i++)s[i]=read();
        for(int i=1;i<=n;i++)a[i]=(struct node){s[i],i};
        for(int i=1;i<=n;i++)flag[i]=0;
        px(1,n);
        for(int i=2;i<=n;i++)if(a[i].s==a[i-1].s)flag[a[i].h]=1;
        printf("%d",s[1]);
        for(int i=2;i<=n;i++)if(flag[i]==0)printf(" %d",s[i]);
        printf("
");
    }
    return 0;
}

 我可能写的不好,如果有问题,请帮忙指出,谢谢。

原文地址:https://www.cnblogs.com/sy666/p/12775564.html