首页 > 技术文章 > BZOJ 4553 [Tjoi2016&Heoi2016]序列 ——CDQ分治 树状数组

SfailSth 2017-04-20 11:23 原文

考虑答案的构成,发现是一个有限制条件的偏序问题。

然后三个维度的DP,可以排序、CDQ、树状数组各解决一维。

#include <map>
#include <cmath>
#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define F(i,j,k) for (int i=j;i<=k;++i)
#define D(i,j,k) for (int i=j;i>=k;--i)
#define ll long long
#define mp make_pair
#define maxn 200005
 
struct node{
    int a,b,c,id,ans;
    void print()
    {printf("ID is %d Upper %d Middle %d Lower %d\n",c,b,a);}
}q[maxn];
 
int n,m;
 
bool cmp1(node x,node y){return x.b<y.b;}
bool cmp2(node x,node y){return x.a<y.a;}
bool cmp3(node x,node y){return x.id<y.id;}
 
int bit[maxn];
 
void add(int x,int f)
{
    for (;x<maxn;x+=x&(-x)) bit[x]=max(bit[x],f);
}
 
void del(int x)
{
    for (;x<maxn;x+=x&(-x)) bit[x]=0;
}
 
int query(int x)
{
    int ret=0;
    for (;x;x-=x&(-x)) ret=max(ret,bit[x]);
    return ret;
}
 
void CDQ(int l,int r)
{
    if (l==r) return;
    int mid=l+r>>1;
    sort(q+l,q+r+1,cmp3);
    CDQ(l,mid);
    sort(q+l,q+mid+1,cmp1);
    sort(q+mid+1,q+r+1,cmp2);
    int now=l;
    F(i,mid+1,r)
    {
        while (now<=mid&&q[now].b<=q[i].a) add(q[now].c,q[now].ans),now++;
        q[i].ans=max(q[i].ans,query(q[i].b)+1);
    }
    F(i,l,now-1) del(q[i].c);
    CDQ(mid+1,r);
}
 
int main()
{
    scanf("%d%d",&n,&m);
    F(i,1,n)
    {
        scanf("%d",&q[i].b);
        q[i].a=q[i].c=q[i].b;
        q[i].id=i; q[i].ans=1;
    }
    F(i,1,m)
    {
        int x,y;
        scanf("%d%d",&x,&y);
        q[x].a=min(q[x].a,y);
        q[x].c=max(q[x].c,y);
    }
    CDQ(1,n);
    int ans=0;
    F(i,1,n) ans=max(ans,q[i].ans);
    printf("%d\n",ans);
}

  

推荐阅读