BestCoder Round #43(LCA+rmq)
来源:互联网 发布:cf23 2网络出现异常 编辑:程序博客网 时间:2024/04/28 11:02
1001:水题
略过
1002:
题意:求(A+B)%P最大值
超时算法:直接双for循环O(n^2)
#include <cstdio>#include <cstring>#include <algorithm>using namespace std;int d[100010];int main(){ int n,p; while(scanf("%d%d",&n,&p)==2) { int tmp; for(int i=0; i<n; i++) { scanf("%d",&tmp); d[i]=(tmp%p); } int ans=0; for(int i=0; i<n-1; i++) for(int j=i+1; j<=n-1; j++) { if(p-d[i]>d[j]) ans=max(d[i]+d[j],ans); else ans=max(d[i]-p+d[j],ans); } printf("%d\n",ans); } return 0;}
AC算法:预处理+剪枝+记忆
思路:先排序,然后判断最大的两位之和是否大于p,如果小于直接输出即可;
如果大于p,则从当前有序的序列中枚举搜索不超过p的情况,枚举过程中通过
记录上次的最大值,将时间复杂度降到O(n),所以总体时间复杂度为O(nlogn)
<p>#include <cstdio>#include <cstring>#include <algorithm>using namespace std;int d[100010];</p><p>int main(){ int n,p; while(scanf("%d%d",&n,&p)==2) { int tmp; for(int i=0; i<n; i++) { scanf("%d",&tmp); d[i]=(tmp%p); } sort(d,d+n); int ans; if(p-d[n-1]>d[n-2]) printf("%d\n",d[n-1]+d[n-2]); else { ans=d[n-1]-p; ans+=d[n-2]; int now=0; for(int i=n-1; i>=1; i--) { for(int j=now; j<i; j++) { if(p-d[i]>d[j]) ans=max(ans,d[i]+d[j]); else { if(j>0) now=j-1;///关键点 break; } if(ans==p-1) break; } if(ans==p-1) break; } printf("%d\n",ans); } } return 0;}</p>
1003:DFS+RMQ
首先用dfs遍历这棵树,标记每个节点第一次被访问时间,在遍历过程中记录当前时刻正在访问的点及其深度
然后寻找某个区间的最近公共祖先时,首先找到这个区间最早被访问的时间以及最晚被访问的时间(rmq),
同时在最早和最晚时间中找寻深度最大的结点所在的时刻,进而找到公共祖先(rmq)
#pragma comment(linker,"/STACK:1024000000,1024000000")#include <cstdio>#include <cstring>#include <vector>#include <algorithm>using namespace std;const int MAX=300001;vector<int> t[MAX];int b[MAX];///记录某个节点第一次被访问的位置int bdp[MAX][20];int bdpt[MAX][20];int s[MAX*2];///记录整个深搜过程int h[MAX*2],hm[MAX*2],hdp[MAX*2][20];bool f[MAX];int pos;int n,m;void dfs(int ct,int d){ b[ct]=pos; s[pos]=ct; h[pos]=d; ++pos; int len=t[ct].size(); for(int i=0; i<len; i++) { if(!f[t[ct][i]]) { f[t[ct][i]]=true; dfs(t[ct][i],d+1); s[pos]=ct; h[pos]=d; ++pos; } }}void initRMQb(int n,int t[]){ for(int i=1; i<=n; ++i) { bdp[i][0]=t[i]; bdpt[i][0]=t[i]; } for(int j=1; j<=hm[n]; j++) { for(int i=1; i+(1<<j)-1<=n; i++) { bdp[i][j]=min(bdp[i][j-1],bdp[i+(1<<(j-1))][j-1]); bdpt[i][j]=max(bdpt[i][j-1],bdpt[i+(1<<(j-1))][j-1]); } }}int rmqb(int x,int y){ int k=hm[y-x+1]; return min(bdp[x][k],bdp[y-(1<<k)+1][k]);}int rmqbt(int x,int y){ int k=hm[y-x+1]; return max(bdpt[x][k],bdpt[y-(1<<k)+1][k]);}void Make_Rmqindex(int n,int b[]){ hm[0]=-1; for(int i=1; i<=n; ++i) { hm[i]=((i&(i-1))==0)?hm[i-1]+1:hm[i-1]; hdp[i][0]=i; } for(int j=1; j<=hm[n]; j++) { for(int i=1; i+(1<<j)-1<=n; i++) { int x=hdp[i][j-1],y=hdp[i+(1<<(j-1))][j-1]; hdp[i][j]=b[x]<b[y]?x:y; } }}int Rmq_Index(int x,int y,int b[]){ int k=hm[y-x+1]; int l=hdp[x][k]; int r=hdp[y-(1<<k)+1][k]; return b[l]<b[r]?l:r;}int main(){ while(scanf("%d",&n)==1) { memset(t,0,sizeof(t)); memset(f,false,sizeof(f)); int x,y; for(int i=1; i<=n-1; ++i) { scanf("%d%d",&x,&y); t[x].push_back(y); t[y].push_back(x); } pos=1; f[1]=true; dfs(1,0); Make_Rmqindex(pos-1,h); initRMQb(n,b); scanf("%d",&m); for(int i=1; i<=m; ++i) { scanf("%d%d",&x,&y); int bt=rmqb(x,y); int et=rmqbt(x,y); int ht=Rmq_Index(bt,et,h); printf("%d\n",s[ht]); } } return 0;}/*122 56 210 99 111 23 14 112 36 76 89 7*/
1004:没有思路
0 0
- BestCoder Round #43(LCA+rmq)
- BestCoder Round #43 (hdu5264 - 5266)(数学,LCA)good
- BestCoder Round #43
- BestCoder Round #43
- lca&rmq
- 【RMQ & LCA】
- RMQ && LCA
- LCA+RMQ
- LCA && RMQ
- LCA+RMQ
- LCA&RMQ
- LCA&RMQ
- LCA&&RMQ
- 【lca】lca转rmq poj1330
- 【lca】lca转rmq解法
- bestcoder:树状数组+lca
- 【RMQ+LCA】ZOJ 3195
- 【RMQ+LCA】POJ 1986
- 让你的软件永生的7个规则
- [转]ubuntu和windows双系统启动顺序的修改
- sort对二维数组进行排序备忘
- Android 优化电池使用时间——确定和监控基座对接状态和类型
- Erlang语言的作者教你如何入手
- BestCoder Round #43(LCA+rmq)
- Milking Time
- ZooKeeper典型应用场景(转)
- 组播地址Multicase address
- Zookeeper-Zookeeper的配置
- Android提权漏洞分析——rageagainstthecage
- Mysql学习笔记备份
- C++中的return、exit与abort
- Tip