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