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

来源:互联网 发布:汉诺塔非递归算法java 编辑:程序博客网 时间:2024/06/06 09:17

该题的意思:按编号递增给出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?

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



0 0
原创粉丝点击