poj 2104 (暴力or划分树)

来源:互联网 发布:淘宝客怎么拉人进qq群 编辑:程序博客网 时间:2024/05/22 15:57

题意就是给m个数,n个询问,问在从a到b的区间里第k大的数是多少

这题有二十秒,纯暴力就可以过~~~和线段树什么的时间还差不多

上代码

#include<iostream>#include<cstdio>#include<algorithm>using namespace std;struct node{int zhi;int weizhi;//值和位置};node a[100010];int cmp(node x,node y){return x.zhi<y.zhi;//这个函数表示以zhi为标准进行排序,附带着把weizhi移过去;}int main(){int i,j,m,n,k,x,y,z;scanf("%d%d",&m,&n);for(i=1;i<=m;i++){scanf("%d",&a[i].zhi);a[i].weizhi=i;//记录位置}sort(a+1,a+m+1,cmp);//排序for(i=1;i<=n;i++){scanf("%d%d%d",&x,&y,&z);for(j=1;j<=m;j++){if(a[j].weizhi>=x&&a[j].weizhi<=y)z--;//从第一个往上找,找到一个在区间内的,z减一个直到找到第k大的;if(z==0){printf("%d\n",a[j].zhi);break;}}}return 0;} 

接下来是划分树的正解:

至于划分数可以看网上的PPT:

代码:

#include<cstdio>#include<cstdlib>#include<cstring>#include<iostream>#include<algorithm>using namespace std;int a[100010];struct node{int p[100010],o[100010];};node t[100];void jianshu(int s,int e,int c){//s是start,e是end,c是层次; if(s==e)return;//若每个层次只有一个数,返回; int mid=(s+e)/2;int x=s;int y=mid+1;int sum=0;//计数,处理有多个a[mid]相同的情况int l=0;//记录有多少个数被划分到左边for(int i=mid;a[i]==a[mid];i--){sum++;}for(int i=s;i<=e;i++){if(a[mid]>t[c].o[i]){l++;t[c+1].o[x++]=t[c].o[i];t[c].p[i]=l;continue;//记得加}if(a[mid]<t[c].o[i]){t[c+1].o[y++]=t[c].o[i];t[c].p[i]=l;continue;}if(a[mid]==t[c].o[i]&&sum){sum--;l++;t[c+1].o[x++]=t[c].o[i];t[c].p[i]=l;continue;}else {t[c+1].o[y++]=t[c].o[i];t[c].p[i]=l;}}jianshu(s,mid,c+1);jianshu(mid+1,e,c+1);}int xunwen(int s,int e,int k,int j,int th,int ceng){if(s==e)return t[ceng].o[s];int mid=(k+j)/2;int x;int y;if(s==k){x=0;y=t[ceng].p[e];}else{x=t[ceng].p[s-1];y=t[ceng].p[e]-x;}if(y>=th){return xunwen(k+x,k+x+y-1,k,mid,th,ceng+1);}else return xunwen(mid+s-x-k+1,mid+e-x-y-k+1,mid+1,j,th-y,ceng+1);}int main(){int i,j,k,m,n,x,y,z;scanf("%d%d",&m,&n);for(i=1;i<=m;i++){scanf("%d",&t[1].o[i]);a[i]=t[1].o[i];}sort(a+1,a+m+1);jianshu(1,m,1);while(n--){int x,y,z;scanf("%d%d%d",&x,&y,&z);printf("%d\n",xunwen(x,y,1,m,z,1));}return 0;}


2 0
原创粉丝点击