zoukankan      html  css  js  c++  java
  • bzoj 2225 [Spoj 2371]Another Longest Increasing

    这道题 连续上升的三元组 且已经按照第一维排好序了。

    直接上CDQ分治即可 当然也是可以2-Dtree解决这个 问题 但是感觉nlog^2 比nsqrt(n)要快一些。。

    算是复习一发CDQ分治吧 也好久没写了。

    原来最长三元上升序列 不是裸的CDQ分治。。我以为是 没细想 最后还是细想了一下实现方式。

    首先CDQ左边 然后对于右边此时x是无序的 考虑排序 在外面排序没用好吧。。

    好吧可能有用但是太过繁琐那种写法 这里推荐暴力sort。。归并没用 因为归并此时复杂度还是nlogn的。

    统计完左边对右边的贡献后 再桶排序复原。再CDQ右边 回来的时候可以进行归并不需要再sort了节省常数。。

    复杂度nlog^2。

    const int MAXN=100010;
    int n,top,ans;
    struct wy
    {
    	int x,y;
    	int id;
    	inline int friend operator <(wy a,wy b){return a.x==b.x?a.id<b.id:a.x<b.x;}
    }t[MAXN],ql[MAXN];
    int b[MAXN],f[MAXN],c[MAXN];
    inline void discrete()
    {
    	sort(b+1,b+1+n);
    	rep(1,n,i)if(i==1||b[i]!=b[i-1])b[++top]=b[i];
    	rep(1,n,i)y(i)=lower_bound(b+1,b+1+top,y(i))-b;
    }
    inline void add(int x,int y)
    {
    	if(y==-1)
    	{
    		while(x<=top)
    		{
    			c[x]=0;
    			x+=x&(-x);
    		}
    		return;
    	}
    	while(x<=top)
    	{
    		c[x]=max(c[x],y);
    		x+=x&(-x);
    	}
    }
    inline int ask(int x)
    {
    	int cnt=0;
    	while(x)
    	{
    		cnt=max(cnt,c[x]);
    		x-=x&(-x);
    	}
    	return cnt;
    }
    inline void CDQ(int l,int r)
    {
    	if(l==r){++f[id(l)];return;}
    	int mid=(l+r)>>1;
    	CDQ(l,mid);
    	sort(t+mid+1,t+r+1);
    	int i=l,j=mid+1;
    	for(int k=l;k<=r+1;++k)
    	{
    		if(j>r)
    		{
    			for(int w=i-1;w>=l;--w)add(y(w),-1);
    			break;
    		}
    		if((i<=mid)&&x(i)<x(j))add(y(i),f[id(i)]),++i;
    		else f[id(j)]=max(f[id(j)],ask(y(j)-1)),++j;
    	}
    	for(int k=mid+1;k<=r;++k)ql[id(k)]=t[k];
    	for(int k=mid+1;k<=r;++k)t[k]=ql[k];
    	CDQ(mid+1,r);
    	i=l;j=mid+1;
    	for(int k=l;k<=r;++k)
    	{
    		if(i<=mid&&x(i)<x(j)||j>r)ql[k]=t[i],++i;
    		else ql[k]=t[j],++j;
    	}
    	for(int k=l;k<=r;++k)t[k]=ql[k];
    }
    int main()
    {
    	freopen("1.in","r",stdin);
    	get(n);
    	rep(1,n,i)get(x(i)),b[i]=get(y(i)),id(i)=i;
    	discrete();
    	CDQ(1,n);
    	for(int i=1;i<=n;++i)ans=max(ans,f[i]);
    	printf("%d
    ",ans);
    	return 0;
    }
    

    这个树状数组清空的时候注意不要暴力清空 再来一遍序列 清成0即可。

  • 相关阅读:
    洛谷P4315 月下“毛景树”(边权维护)
    Water Tree CodeForces
    P3384 【模板】树链剖分
    Codeforces 161D Distance in Tree(树的点分治)
    git命令及使用方法
    vue下拉刷新,下拉加载更多
    Vue中 v-for 生成样式并默认选中第一个样式
    js面向对象实现分页版轮播图
    js面向对象实现购物车
    js面向对象实现放大镜
  • 原文地址:https://www.cnblogs.com/chdy/p/12470461.html
Copyright © 2011-2022 走看看