首页 > 代码库 > SOJ--4393: LaoB's problem1

SOJ--4393: LaoB's problem1

描述

一个数列包含n(1<n<=100000)个元素,这些元素可能相同 对这个数列有m(1<=m<=100000)个询问, 每个询问包含一个序号x,请回答数列中数值小于第x个元素的元素的总和

Input

第一行包含一个数t代表总的测试样例数
每组样例包含4行
第一行包含一个整数n代表数列的长度
第二行包含n个小于1000的正整数用空格隔开
第三行包含一个整数m代表询问的个数
第四行包含m个在1到n之间的整数代表询问序号

Output

每组输出结果包含m个由空格隔开的整数代买m次询问的结果

Example Input

2
4
255 139 58 412
5
1 1 2 3 3
5
427 563 289 203 326
4
3 1 4 4

Example Output

197 197 58 0 0
203 818 0 0

解析:这道题不难,主要是有容易考虑不到的地方,我是通过结构体来存放数值和编号,然后以数值的大小排序,接着就计算每一个编号的结果值存放到res数组中,容易出错的是没有考虑数值可能重复的情况

比如这组数据
5
20   21   20    21   20
5
1     2     3     4
输出
0    60    0     60     0
如果考虑了这组数据应该问题就不大了。

贴一下自己AC的代码
#include<stdio.h>
#include<algorithm>
using std::sort;
//定义全局变量
const int M=100000+5;
struct data{
	int n;
	int num;
}a[M];
int b[M];
int res[M];
//优先按照数值的大小进行排序,如果数值相等再按照编号升序
bool cmp(data x,data y)
{
	if(x.n<y.n)
	{
		return true;
	}else if(x.n>y.n)
	{
		return false;
	}else{
		return x.num<y.num;
	}
}
int main()
{
	int t;
	scanf("%d",&t);
	while(t--)
	{
		int n,cnt=1;
		scanf("%d",&n);
		for(int i=0; i<n; ++i)
		{
			scanf("%d",&a[i].n);
			a[i].num=i+1;
		}
		int m;
		scanf("%d",&m);
		//输入询问的序号
		for(int i=0; i<m; ++i)
		{
			scanf("%d",&b[i]);
		}
		//对数组a中的数据进行排序
		sort(a,a+n,cmp);
		//统计小于每个序号所对应值之和
		res[a[0].num]=0;
		for(int i=1; i<n; ++i)
		{
			if(a[i].n!=a[i-1].n)
			{
				res[a[i].num]=res[a[i-1].num]+a[i-1].n;
				int temp=i-1;
				//如果前面全是相同元素
				while(temp>0&&a[i-1].n==a[temp-1].n)
				{
					res[a[i].num]+=a[temp-1].n;
					--temp;
				}
			}else{
				//与前面的元素相同
				res[a[i].num]=res[a[i-1].num];
			}
		}
		//输出结果
		for(int i=0; i<m; ++i)
		{
			printf("%d",res[b[i]]);
			//输出空格,最后一个数字则输出换行
			if(i!=m-1)
			{
				printf(" ");
			}else{
				printf("\n");
			}
		}
		
	}
}


SOJ--4393: LaoB's problem1