oj_64 新年组队
来源:互联网 发布:网络安全工程师职责 编辑:程序博客网 时间:2024/05/21 07:47
题目描述
Problem Description
BNU ACM校队有n名队员,从1到n标号,每名队员根据自身情况拥有一个特征值,其中第i名队员的特征值是a[i]。现在BOSS问了m个问题,每个问题给定[l,r],要求小Q同学马上从标号位于区间[l,r]内的队员中选出两名队员,使得这两名队员的特征值相同,并且不默契度要尽可能小,两名队员的不默契度定义为两名队员标号之差的绝对值。对此小Q同学倍感压力,急需你的帮助。
Input
第一行包含2个整数n、m。
第二行包含n个整数a[1]、a[2]、…、a[n],保证0<=a[i]<2^31。
接下来m行,每行包含2个整数l、r,请注意所给的l、r均是经过加密的,解密方式是l=l xor lastans、r=r xor lastans,其中lastans表示上一次操作的输出结果,初始lastans=0,保证解密后1<=l<=r<=n。
对于30%的数据,1<=n,m<=5000。
对于60%的数据,1<=n,m<=50000。
对于100%的数据,1<=n,m<=500000。
Output
输出m行,每行包含一个整数,表示最小的两名队员的不默契度,如果不能选出满足条件的两名队员,请输出-1。
Sample Input
5 3
1 1 2 5 2
1 5
3 5
-4 -6
Sample Output
1
-1
2
题解
这题用分块和rmq都可以,我打的是分块,分成k块f[i][j]记录[i,j]的最小不默契度,用一个dp转移,f[i][j]=min(min(f[i][j],f[i+1][j]),f[i][j-1])
具体做法可以看我的注释。
但是本题的数据非常水,全部输出1可以得55分。记住f数组初始化时要从0到k+1。
AC代码
#include<cstdio>#include<iostream>#include<cmath>#include<algorithm>#include<cstring>#define N 500010#define K 710using namespace std;int a[N],b[N],c[N],d[N],f[K][K],n,m,p,q,ans,g,k,e[N];bool cmp(int p,int q){ if(a[p]==a[q])return p<q; return a[p]<a[q];}int main(){ freopen("data.txt","r",stdin); freopen("64.txt","w",stdout); scanf("%d%d",&n,&m); k=sqrt(n); if(n%k==0)g=n/k; else g=n/k+1; for(int i=0;i<=k+1;i++) for(int j=0;j<=k+1;j++) f[i][j]=2147483647; for(int i=1;i<=n;i++){ scanf("%d",&a[i]); b[i]=i; } sort(b+1,b+n+1,cmp);// for(int i=1;i<=n;i++)printf("%d ",a[b[i]]);// printf("\n"); for(int i=1;i<=n;i++)c[i]=(i-1)/g+1; for(int i=1;i<n;i++) if(a[b[i+1]]==a[b[i]]){ d[b[i]]=b[i+1]; e[b[i+1]]=b[i]; f[c[b[i]]][c[b[i+1]]]=min(f[c[b[i]]][c[b[i+1]]],b[i+1]-b[i]); }// for(int i=1;i<=k;i++){// for(int j=i+1;j<=k;j++){// f[i][j]=min(min(f[i+1][j],f[i][j]),f[i][j-1]);// }// } for(int i=1;i<=k;i++){ for(int j=1;j<=k-i;j++){ f[j][j+i]=min(min(f[j+1][j+i],f[j][j+i]),f[j][j+i-1]); } }// for(int i=1;i<=k;i++){// for(int j=1;j<=k;j++){// printf("%d ",f[i][j]);// }// printf("\n");// } for(int i=1;i<=m;i++){ scanf("%d%d",&p,&q); p=p^ans; q=q^ans; ans=f[c[p]+1][c[q]-1]; for(int j=p;j<=c[p]*g;j++)if(d[j]!=0&&d[j]<=q)ans=min(ans,d[j]-j); for(int j=(c[q]-1)*g+1;j<=q;j++)if(e[j]!=0&&e[j]>=p)ans=min(ans,j-e[j]); if(ans==2147483647)ans=-1; printf("%d\n",ans); }}
0 0
- oj_64 新年组队
- 作业1:新年组队
- GFOJ problem64 新年组队 解题报告
- 组队
- 新年
- 新年
- 新年
- 新年
- 新年
- 新年
- 新年
- 新年
- 新年
- 新年
- 新年
- 新年
- 新年
- 新年
- C++动态内存管理核心知识点总结
- Mybatis Generator配置说明
- 分词统计(四)唐宋元诗人吟诗作词的时候,最偏爱哪些词语呢?(附上AI写的1000句诗!)
- Git忽略规则及.gitignore规则不生效的解决办法
- 09-jQuery和ajax-2
- oj_64 新年组队
- 炫酷安卓垃圾回收动画
- 关于公司层次的思考
- java动态代理与静态代理
- 10-jQuery和ajax-3-ajax封装
- 数据结构—树与二叉树篇II
- 算法——分治法之棋盘覆盖
- nodejs安装配置
- JQueryEasyUI 组件 布局 portal组件