timus 1613. For Fans of Statistics【该题超时的代码记录】

该题的意思:按编号递增给出n(0<n<70000)个点的值(点的编号从1~n),给出m(1<=m<70000)条查询数据

数据输入格式为a b c(从编号a到编号b之间是否有值是为c的,如果有则返回1,没有返回0

具体的意思可以进链接: http://acm.timus.ru/problem.aspx?space=1&num=1613

这里只给出超时的代码(可能这道题C++解决真的得用上STL):

case 1:

/*
树的子节点最多三个
左边的子节点(left)表示小于根节点的值的编号
右边的子节点(right)表示大于根节点的值的编号
中间的子节点(mid)表示等于根节点的值的编号
树分插入(insert)和查询(search)操作
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
using namespace std;
struct Node
{
	int key,left,right,mid;
};
Node nn[70007];
int n,m,a,b,c;
void insert(int x,int y)
{
	if(nn[x].key>nn[y].key)
	{
		if(nn[y].right!=-1)insert(x,nn[y].right);
		else nn[y].right=x;
	}
	else if(nn[x].key<nn[y].key)
	{
		if(nn[y].left!=-1)insert(x,nn[y].left);
		else nn[y].left=x;
	}
	else
	{
		if(nn[y].mid!=-1)insert(x,nn[y].mid);
		else nn[y].mid=x;
	}
}
bool search(int loc)
{
	if(nn[loc].key>c&&nn[loc].left!=-1)return search(nn[loc].left);
	else if(nn[loc].key>c)return false;
	else if(nn[loc].key<c&&nn[loc].right!=-1)return search(nn[loc].right);
	else if(nn[loc].key<c)return false;
	else
	{
		if(loc>=a&&loc<=b)return true;
		else if(nn[loc].mid!=-1)return search(nn[loc].mid);
		else return false;
	}
}
int main()
{
	int i;
	while(scanf("%d",&n)!=-1)
	{
		for(i=1;i<=n;i++)
			nn[i].key=nn[i].left=nn[i].right=nn[i].mid=-1;
		scanf("%d",&nn[1].key);
		for(i=2;i<=n;i++)
		{
			scanf("%d",&nn[i].key);
			insert(i,1);
		}
		scanf("%d",&m);
		char ch[70007];
		for(i=0;i<m;i++)
		{
			scanf("%d%d%d",&a,&b,&c);
			bool ff=search(1);
			if(ff)ch[i]='1';
			else ch[i]='0';
		}
		ch[m]='\0';
		printf("%s\n",ch);
	}
	return 0;
}

稍稍做了点优化,时间可以稍微快一些的sort+二分查询

case 2:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<cstdlib>
using namespace std;
struct Node
{
	int key,num;
};
Node nn[70007];
bool cmp(Node aa,Node bb) //排序规则,按照先按键值从小到大排,如果键值相同,则按编号从小到大排序
{
	if(aa.key<bb.key)return true;
	else if(aa.key==bb.key&&aa.num<bb.num)return true;
	return false;
}
int a,b,c,n;
bool find(int st,int ed)
{
	int i;
	if(st==ed&&nn[st].key==c)
	{
		if(nn[st].num>=a&&nn[st].num<=b)return true;
		if(nn[st].num>=a)
		{
		  for(i=st-1;i>=0;i--)
			if(nn[i].key!=nn[i+1].key)break;
			else if(nn[i].num>=a&&nn[i].num<=b)return true;
		}
		if(nn[ed].num<=b)
		{
		  for(i=ed+1;i<n;i++)
			if(nn[i].key!=nn[i-1].key)break;
			else if(nn[i].num>=a&&nn[i].num<=b)return true;
		}
	    return false;
	}
	else if(st==ed)return false;
	else if(st+1==ed)
	{
		if(nn[st].num>=a&&nn[st].num<=b&&nn[st].key==c)return true;
		else if(nn[st].key==c&&nn[st].num>=a)
		{
			  for(i=st-1;i>=0;i--)
			    if(nn[i].key!=nn[i+1].key)break;
			    else if(nn[i].num>=a&&nn[i].num<=b)return true;
		}
		if(nn[ed].num>=a&&nn[ed].num<=b&&nn[ed].key==c)return true;
		else if(nn[ed].key==c&&nn[ed].num<=b)
		{
		      for(i=ed+1;i<n;i++)
			   if(nn[i].key!=nn[i-1].key)break;
			   else if(nn[i].num>=a&&nn[i].num<=b)return true;
		}
		return false;
	}
	else if(st+1==ed)return false;
	else
	{
		int mid=(st+ed)/2;
		if(nn[mid].key>c)return find(st,mid-1);
		else if(nn[mid].key<c)return find(mid+1,ed);
		else return find(mid,mid);
	}
}
int main()
{
	int i,m;
	bool ff;
	while(scanf("%d",&n)!=-1)
	{
		for(i=0;i<n;i++)
		{
			scanf("%d",&nn[i].key);
			nn[i].num=i+1;
		}
		sort(nn,nn+n,cmp);
		scanf("%d",&m);
		char ch[70007];
		for(i=0;i<m;i++)
		{
			scanf("%d%d%d",&a,&b,&c);
			ff=find(0,n-1);
			if(ff)ch[i]='1';
			else ch[i]='0';
		}
		ch[m]='\0';
		printf("%s\n",ch);
	}
	return 0;
}

case 2和case 1的优化只是在于键值相同时编号从小到大排序了,所以case 2的find函数里面的多了一点优化。可以这样的优化还是在另一组数据上(应该是更多元素的测试数据)超时了!

这两种方法是不是还有可以优化的地方呢?是不是一定要用上STL?

把几个超时的代码放在这里,留下个思考!

时间: 2024-10-13 11:23:24

timus 1613. For Fans of Statistics【该题超时的代码记录】的相关文章

URAL 1613. For Fans of Statistics(STL 数学啊 )

题目链接:http://acm.timus.ru/problem.aspx?space=1&num=1613 1613. For Fans of Statistics Time limit: 1.0 second Memory limit: 64 MB Have you ever thought about how many people are transported by trams every year in a city with a ten-million population whe

Ural 1613 For Fans of Statistics(vector应用)

题目: For Fans of Statistics Time Limit:1000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64 Description Have you ever thought about how many people are transported by trams every year in a city with a ten-million population where one in th

URAL 1613 For Fans of Statistics

题意:就是给了你n个数字,他们的编号为1到n,然后接下来有q个询问,每次询问有 l,r,x, 就是问你 是否 在编号区间[l,r]内有数字X出现过,有就是1,无就是0,最后一起输出来 输入其实数字是有重复的,所以先用map离散化,然后再用map跟vector 的邻接表连接,讲编号放入邻接表里面,并升序排序,然后询问的时候直接二分查找编号,是否存在就可以了,手写的二分 一直WA,莫名其妙,改用Lower_bound就过了 int n; map<string ,int>mark,mp; vecto

Ural 1613-For Fans of Statistics(vector)

1613. For Fans of Statistics Time limit: 1.0 second Memory limit: 64 MB Have you ever thought about how many people are transported by trams every year in a city with a ten-million population where one in three citizens uses tram twice a day? Assume

STL--G - For Fans of Statistics(两个判断条件-二分)

G - For Fans of Statistics Time Limit:1000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u Submit Status Description Have you ever thought about how many people are transported by trams every year in a city with a ten-million population

For Fans of Statistics

For Fans of Statistics Time limit: 1.0 secondMemory limit: 64 MB Have you ever thought about how many people are transported by trams every year in a city with a ten-million population where one in three citizens uses tram twice a day? Assume that th

poj水题-1579 将递归记录会变快

短平快递归肯定卡死,这里需要了解一个情况. 1.递归是否在很多情况再做重复工作? 2.由递归生成的“大面积数据”是否是由“小范围数据”组合而来? 如果都回答“是”.就强烈推荐“记笔记方式”.如果有笔记记录,那么查笔记,否则递归. #include <stdio.h> long s[21][21][21] = {0}; int w(int a,int b,int c) { if (a <= 0 || b <= 0 || c <= 0) return s[0][0][0]=1;

2.1【欢乐向】逆向刷题被虐哭日常记录

2.1[欢乐向]逆向刷题被虐哭日常记录 前面好多题之前做了也没记录,懒得整了,直接从剩下的几个开始: Getit 这一段是解密的关键,后面的是把flag写入文档又给删了. 其实可以修改程序逻辑让他别删,但是我不会. ? 逆着来推一边,不会写py,用c写个. ? ? ?不应当,我大概是忘了加括号. ? ???我觉得我的没啥问题,去网上查了查相关的: ? ? ? 在IDA里没看到有S,咱也不知道咋回事. ? ? ? ? ? no-strings-attached 直接扔IDA瞅瞅: ? ? 挨个函数

【南阳OJ分类之语言入门】80题题目+AC代码汇总

声明: 题目部分皆为南阳OJ题目. 代码部分包含AC代码(可能不止一个)和最优代码,大部分都是本人写的,并且大部分为c代码和少部分c++代码and极少java代码,但基本都是c语言知识点,没有太多差别,可能代码有的写的比较丑,毕竟知识有限. 语言入门部分题基本都较为简单,是学习编程入门的很好练习,也是ACM的第一步,入门的最佳方法,望认真对待. 本文由csdn-jtahstu原创,转载请注明出处,欢迎志同道合的朋友一起交流学习.本人QQ:1373758426和csdn博客地址. now begi