BZOJ 4553: [Tjoi2016&Heoi2016]序列
2016-05-20 19:58
399 查看
我就不懂了怎么又是线段树啊(好吧其实可以写平衡树)
f[i]可以从f[j](a[j]<=l[i]&&r[j]<=a[i])转移过来
观察条件发现就是某个矩阵里的权最大的点
权值线段树套权值线段树就可以n(logn)^2了,但是空间也是这么多,会MLE
所以三维偏序什么的还是cdq分治吧
然后就轻易地过掉了
f[i]可以从f[j](a[j]<=l[i]&&r[j]<=a[i])转移过来
观察条件发现就是某个矩阵里的权最大的点
权值线段树套权值线段树就可以n(logn)^2了,但是空间也是这么多,会MLE
所以三维偏序什么的还是cdq分治吧
然后就轻易地过掉了
#include<cstdio> #include<iostream> #include<cstring> #include<cmath> #include<queue> #include<vector> #include<algorithm> #include<map> #include<set> #define rep(i,l,r) for(int i=l;i<=r;i++) #define per(i,r,l) for(int i=r;i>=l;i--) #define mmt(a,v) memset(a,v,sizeof(a)) #define tra(i,u) for(int i=head[u];i;i=e[i].next) using namespace std; const int N=100000+5; int l ,r ,a ; struct Node{ int l,r,mx,ti; }tr[N<<2]; #define lc o<<1 #define rc o<<1|1 int T; void clr(){T++;} void refresh(int o){ if(tr[o].ti!=T)tr[o].ti=T,tr[o].mx=0; } void pushup(int o){ tr[o].mx=max(tr[lc].mx,tr[rc].mx); } void update(int o,int p,int v){ refresh(o); int l=tr[o].l,r=tr[o].r; if(l==r)tr[o].mx=max(tr[o].mx,v); else{ int mid=l+r>>1; if(p<=mid)update(lc,p,v),refresh(rc); else update(rc,p,v),refresh(lc); pushup(o); } } int query(int o,int a,int b){ int l=tr[o].l,r=tr[o].r; if(l==a&&b==r){refresh(o);return tr[o].mx;} else{ int mid=l+r>>1; if(b<=mid)return query(lc,a,b); else if(mid<a)return query(rc,a,b); else return max(query(lc,a,mid),query(rc,mid+1,b)); } } void build(int o,int l,int r){ tr[o].l=l;tr[o].r=r;tr[o].mx=0; if(l==r)return; int mid=l+r>>1; build(lc,l,mid);build(rc,mid+1,r); } bool cmp1(int i,int j){return a[i]<a[j];} bool cmp2(int i,int j){return l[i]<l[j];} int p ,ans ; void cdq(int x,int y){ if(x==y)return; int mid=x+y>>1; cdq(x,mid); sort(p+x,p+mid+1,cmp1); sort(p+mid+1,p+y+1,cmp2); clr(); int j=mid+1; rep(i,x,mid){ while(j<=y&&l[p[j]]<a[p[i]]) ans[p[j]]=max(ans[p[j]],query(1,1,a[p[j]])+1),j++; update(1,r[p[i]],ans[p[i]]); } while(j<=y)ans[p[j]]=max(ans[p[j]],query(1,1,a[p[j]])+1),j++; sort(p+mid+1,p+y+1); cdq(mid+1,y); } int main(){ //freopen("a.in","r",stdin); int n,m;scanf("%d%d",&n,&m); rep(i,1,n)scanf("%d",&a[i]),l[i]=r[i]=a[i],p[i]=i; while(m--){ int x,y;scanf("%d%d",&x,&y); l[x]=min(l[x],y); r[x]=max(r[x],y); } build(1,1,n); rep(i,1,n)ans[i]=1; cdq(1,n); int ret=0; rep(i,1,n)ret=max(ret,ans[i]); printf("%d\n",ret); return 0; }
相关文章推荐
- 从Eclipse转移到IntelliJ IDEA的一点心得
- 用c++实现单向链表和双向链表
- Office10安装提示:Microsoft Office 2010 安装要求您的计算机上安装 MSXML 版本 6.10.1129.0
- 图像配准】基于灰度的模板匹配算法(一):MAD、SAD、SSD、MSD、NCC、SSDA、SATD算法
- Android之ListView优化基本
- Linux_2_Navigation
- 内容模式
- querySelectorAll对象无ID的题
- Wolf and Rabbit (hdu_1222) 欧几里德
- 【IPC通信】有名管道FIFO
- [No000097]程序员面试题集【下】
- django ajax 应用实例
- java代码中发送http请求的DnsResolver使用问题
- Java回调机制(callback)
- BZOJ 3239 Discrete Logging
- 求生之路
- Ubuntu 16.04 安装中文输入法(Ubuntu 16.04 install chinese input method)
- HDU 1233 还是畅通工程
- Java之ArrayList
- 浏览器刷新页面后向服务器发出两次请求的问题