BZOJ 4553: [Tjoi2016&Heoi2016]序列

来源:互联网 发布:淘宝高仿鞋子店铺名字 编辑:程序博客网 时间:2024/06/15 01:26

我就不懂了怎么又是线段树啊(好吧其实可以写平衡树)

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[N],r[N],a[N];struct Node{int l,r,mx,ti;}tr[N<<2];#define lc o<<1#define rc o<<1|1int 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[N],ans[N];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;}


0 0
原创粉丝点击