【CF 474E】Pillars
来源:互联网 发布:声鉴软件 编辑:程序博客网 时间:2024/05/01 14:09
【CF 474E】Pillars
离散化+线段树dp
大半夜写出来了。。。好长好长好长好长好挫……先把高度排序离散化 我又开了个哈希数组用来查某点对应离散后的点 然后遍历每个点时二分出满足题意的区间(1~h-d)(h+d~max) 然后线段树查两个区间当前最大长度的序列 累计到当前点对应的树内点 同时更新他的父亲点们的最大长度 再把之前最大长度的末尾作为当前点的前驱 如果没有就用当前点自己做前驱 最后输出树根存的节点的前驱们(即为树内最长的序列) 各种节点哈希的有点混乱……代码……看乱了就别看了= =我现在看的都有点乱
代码如下:
#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#define LL long long#define sz 100000#define sr "%lld"using namespace std;typedef struct Hash//离散化后哈希用{ LL h;//当前点高度 int id;//离散前节点号 bool operator < (const struct Hash a)const { return h < a.h; }}Hash;typedef struct Node//线段树{ int len,Maxid,id;}Node;Node lt[sz*4+100];//线段树Hash hs[sz+2];//离散int to[sz+2];//记录某点离散后对应点序号int pre[sz+2];//前驱int n;void ReBuild(int site,int l,int r)//初始化线段树{ if(l == r)//叶子节点初始长度0 节点号为离散后标号 最大序列节点为自己 { lt[site].len = 0; lt[site].Maxid = site; lt[site].id = l; return; } int m = (l+r)>>1; ReBuild(site<<1,l,m); ReBuild(site<<1|1,m+1,r); lt[site].len = lt[site].Maxid = 0;//树内节点长度 最大序列节点初始0}int LowerBound(LL x)//二分查<= h-d的最大下标{ int l = 1,r = n,mid,ans = 0; while(l <= r) { mid = (l+r)>>1; if(hs[mid].h <= x) { ans = mid; l = mid+1; }else r = mid-1; } return ans;}int UpperBound(LL x)//二分查>= h+d的最小下标{ int l = 1,r = n,mid,ans = 0; while(l <= r) { mid = (l+r)>>1; if(hs[mid].h >= x) { ans = mid; r = mid-1; }else l = mid+1; } return ans;}int Find(int site,int l,int r,int ll,int rr)//找当前点前的最长序列{ if(l == ll && r == rr) { return lt[site].Maxid;//返回当前结点最长序列下标 } int mid = (l+r)>>1; int a,b; if(mid >= rr) return Find(site<<1,l,mid,ll,rr); else if(mid < ll) return Find(site<<1|1,mid+1,r,ll,rr); else { a = Find(site<<1,l,mid,ll,mid); b = Find(site<<1|1,mid+1,r,mid+1,rr); if(lt[a].len > lt[b].len) return a; else return b; }}void Updata(int site,int l,int r,int id,int mid)//更新树内当前点之前最长序列{ if(l == r && l == id) { lt[site].len = lt[mid].len+1; if(mid)//没有更新当前点前驱为自己 { pre[hs[id].id] = hs[lt[mid].id].id; }else pre[hs[id].id] = hs[id].id;//否则为最长序列末端 return; } int md = (l+r)>>1; if(md >= id) { Updata(site<<1,l,md,id,mid); if(lt[site].len < lt[site<<1].len) { lt[site].Maxid = lt[site<<1].Maxid; lt[site].len = lt[site<<1].len; } } else { Updata(site<<1|1,md+1,r,id,mid); if(lt[site].len < lt[site<<1|1].len) { lt[site].Maxid = lt[site<<1|1].Maxid; lt[site].len = lt[site<<1|1].len; } }}void Print(int x)//递归输出最长序列{ if(x == pre[x]) { printf("%d",x); return; } Print(pre[x]); printf(" %d",x);}int main(){ int d,i,x1,x2,l; scanf("%d %d",&n,&d); for(i = 1; i <= n; ++i)//建立哈希数组 { scanf(sr,&hs[i].h); hs[i].id = i; } if(d == 0)//特判距离0直接1~n输出 { printf("%d\n",n); for(i = 1; i < n; ++i) printf("%d ",i); printf("%d\n",n); return 0; } sort(hs+1,hs+1+n);//按高度对哈希数组排序 for(i = 1; i <= n; ++i)//安插哈希节点 { to[hs[i].id] = i; } ReBuild(1,1,n);//建树 lt[0].len = lt[0].Maxid = 0; for(i = 1; i <= n; ++i) { l = LowerBound(hs[to[i]].h-d);//二分找h-d if(l) x1 = Find(1,1,n,1,l);//找到则查到最长序列 else x1 = 0; l = UpperBound(hs[to[i]].h+d);//二分找h+d if(l) x2 = Find(1,1,n,l,n); else x2 = 0; if(lt[x1].len > lt[x2].len) Updata(1,1,n,to[i],x1);//用最长序列更新树内当前结点 else Updata(1,1,n,to[i],x2); } printf("%d\n",lt[1].len); Print(hs[lt[lt[1].Maxid].id].id); puts(""); return 0;}
0 0
- 【CF 474E】Pillars
- Codeforces 474 E. Pillars
- CodeForces 474 E. Pillars
- codeforces 474E Pillars(线段树+dp)
- Codeforces 474E Pillars dp+线段树
- Codeforces 474E Pillars dp+线段树
- 【CODEFORCES】 E. Pillars
- Codeforces 474E Pillars dp+线段树(水
- Codeforces 474E Pillars(论数据的重要性)
- E. Pillars(Codeforces Round #271)
- Codeforces 474E Pillars【Dp+线段树+二分+离散化】好题~
- Codeforces Round #271 (Div. 2) E. Pillars
- cf-e
- Codeforces Round #271 (Div. 2)——E. Pillars
- e-Government CF 163E
- e-Government CF 163E
- cf 163e e-Government
- CF 208E
- CSS3属性box-flex
- hdoj5253
- OC_Notifications(通知)
- IO流笔记02
- 从零开始学习iOS开发-股票记帐本1.0(1)
- 【CF 474E】Pillars
- Practice Round APAC test Problem A. Bad Horse 2-sat
- 使用专用硬件加速深度卷积神经网络
- 风险投资与经营者 分成利润
- 正则表达式知识点汇集
- NGUI 无法刷新 shader参数的问题
- HDU 2032
- RMAN正确地删除Archivelog以及设置有备库的归档删除策略
- HDU 4086