BZOJ 4553: [Tjoi2016 & Heoi2016] sequence set tree tree partition CDQ

title

BZOJ 4553

LUOGU 4093

Description

Jia Yuan sister birthday, her partner bought a little fun toy from a treasure given to him. There are a number of columns on the toy, the number of columns in the value of certain items may change, but at the same time a maximum of only one value changes. Jia Yuan sister has now developed a possibility of change of all, she would like to ask you, can choose a subsequence such that any one variation, the sequences are not drop? Would you please tell her the longest length to this sequence.

Note: Each change at most one value changes. In the sample input \ (1 \) , all of the changes are:

1 2 3
2 2 3
1 3 3
1 1 3
1 2 4

Select a sub-sequence of the original sequence, i.e. the sequences are not drop any variation in sample input (2 \) \ , all changes are:

3 3 3
3 2 3

Selecting a subsequence of the first element and the third element, or the second element and third element, and can meet the requirements.

Input

The first line of input has two positive integers \ (n-, m \) , respectively, represents the number of changes in length and sequence. The next line have \ (n-\) number, this number represents a column of the original state. Next \ (m \) rows, each row having \ (2 \) number \ (X, Y \) , represents the number sequence \ (X \) item may changed to \ (Y \) value. \ (. 1 \ leqslant X \ n-leqslant \) . All figures are positive integers, and less than equal to \ (100,000 \) .

Output

Output an integer representing the corresponding answer.

Sample Input

3 4
1 2 3
1 2
2 3
2 1
3 4

Sample Output

3

analysis

This problem can be transformed into a sequence \ (Dp \) , a sequence of elements disposed the original value \ (a_i \) , the maximum value is \ (Max_i \) , the minimum value is \ (min_i \) , then:
\ [f_i = f_j + 1 ( j \ leqslant i, Max_j \ leqslant a_i, a_j \ leqslant min_i) \]

So this is a partial order of three-dimensional problem.

Tree or tree can be set \ (CDQ \) divide and conquer to solve.

Tree cover tree, you can use \ (BIT \) sets \ (SGT \) , the two conditions can be maintained.

The \ (CDQ \) partition can do this:

For the interval \ ([L, R & lt] \) , if this element \ (I \) in (MID \) \ foregoing, we will use \ ((Max_i, a_i) \ ) as its weight; otherwise, with \ ((a_i, min_i) \ ) as its weight.

In this way, you can achieve the above idea: using front to update later.

code

\ (CDQ \) Divide and Conquer

#include<bits/stdc++.h>

const int maxn=3e5+10,MaxV=3e5;
typedef int iarr[maxn];

namespace IO
{
    char buf[1<<15],*fs,*ft;
    inline char getc() { return (ft==fs&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),ft==fs))?0:*fs++; }
    template<typename T>inline void read(T &x)
    {
        x=0;
        T f=1, ch=getchar();
        while (!isdigit(ch) && ch^'-') ch=getchar();
        if (ch=='-') f=-1, ch=getchar();
        while (isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48), ch=getchar();
        x*=f;
    }

    char Out[1<<24],*fe=Out;
    inline void flush() { fwrite(Out,1,fe-Out,stdout); fe=Out; }
    template<typename T>inline void write(T x,char str)
    {
        if (!x) *fe++=48;
        if (x<0) *fe++='-', x=-x;
        T num=0, ch[20];
        while (x) ch[++num]=x%10+48, x/=10;
        while (num) *fe++=ch[num--];
        *fe++=str;
    }
}

using IO::read;
using IO::write;

template<typename T>inline bool chkMin(T &a,const T &b) { return a>b ? (a=b, true) : false; }
template<typename T>inline bool chkMax(T &a,const T &b) { return a<b ? (a=b, true) : false; }

namespace BIT
{
    int c[maxn];
    inline int lowbit(int x) { return x & -x; }
    inline void add(int x,int k) { while (x<=MaxV) !k ? c[x]=0 : chkMax(c[x],k), x+=lowbit(x); }
    inline int ask(int x) { int ans=0; while (x) chkMax(ans,c[x]), x-=lowbit(x); return ans; }
}

using BIT::add;
using BIT::ask;

struct Orz{int x,y,id;}o[maxn];
inline bool cmp(const Orz &a,const Orz &b)
{
    return a.x<b.x || (a.x==b.x && a.id<b.id);
}

iarr a,f,Max,Min;
inline void CDQ(int l,int r)
{
    if (l==r) { chkMax(f[l],1); return ; }
    int mid=(l+r)>>1;
    CDQ(l,mid);
    for (int i=l; i<=r; ++i)
    {
        if (i<=mid) o[i].x=a[i], o[i].y=Max[i];
        else o[i].x=Min[i], o[i].y=a[i];
        o[i].id=i;
    }
    std::sort(o+l,o+r+1,cmp);
    for (int i=l; i<=r; ++i)
    {
        if (o[i].id<=mid) add(o[i].y,f[o[i].id]);
        else chkMax(f[o[i].id],ask(o[i].y)+1);
    }
    for (int i=l; i<=r; ++i) add(o[i].y,0);
    CDQ(mid+1,r);
}

int main()
{
    int n,m;read(n);read(m);
    for (int i=1; i<=n; ++i) read(a[i]), Max[i]=Min[i]=a[i];
    for (int i=1,x,v; i<=m; ++i)
    {
        read(x);read(v);
        chkMax(Max[x],v);
        chkMin(Min[x],v);
    }
    CDQ(1,n);
    int ans=0;
    for (int i=1; i<=n; ++i) chkMax(ans,f[i]);
    write(ans,'\n');
    IO::flush();
    return 0;
}

Tree cover Tree Dafa is good!

#include<bits/stdc++.h>

const int maxn=1e5+10,MaxV=1e5;
typedef int iarr[maxn];

namespace IO
{
    char buf[1<<15],*fs,*ft;
    inline char getc() { return (ft==fs&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),ft==fs))?0:*fs++; }
    template<typename T>inline void read(T &x)
    {
        x=0;
        T f=1, ch=getchar();
        while (!isdigit(ch) && ch^'-') ch=getchar();
        if (ch=='-') f=-1, ch=getchar();
        while (isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48), ch=getchar();
        x*=f;
    }

    char Out[1<<24],*fe=Out;
    inline void flush() { fwrite(Out,1,fe-Out,stdout); fe=Out; }
    template<typename T>inline void write(T x,char str)
    {
        if (!x) *fe++=48;
        if (x<0) *fe++='-', x=-x;
        T num=0, ch[20];
        while (x) ch[++num]=x%10+48, x/=10;
        while (num) *fe++=ch[num--];
        *fe++=str;
    }
}

using IO::read;
using IO::write;

template<typename T>inline bool chkMin(T &a,const T &b) { return a>b ? (a=b, true) : false; }
template<typename T>inline bool chkMax(T &a,const T &b) { return a<b ? (a=b, true) : false; }
template<typename T>inline T min(T a,T b) { return a<b ? a : b; }
template<typename T>inline T max(T a,T b) { return a>b ? a : b; }

struct SGT
{
    struct Orz{int l,r,z;}c[maxn*100]; int cnt;
    inline void Change(int &x,int l,int r,int pos,int k)
    {
        if (!x) x=++cnt;
        chkMax(c[x].z,k);
        if (l==r) return ;
        int mid=(l+r)>>1;
        if (pos<=mid) Change(c[x].l,l,mid,pos,k);
        else Change(c[x].r,mid+1,r,pos,k);
    }

    inline int query(int x,int l,int r,int tl,int tr)
    {
        if (!x || l>tr || r<tl) return 0;
        if (tl<=l && r<=tr) return c[x].z;
        int mid=(l+r)>>1;
        return max(query(c[x].l,l,mid,tl,tr),query(c[x].r,mid+1,r,tl,tr));
    }
} sgt;

iarr a,Max,Min,f;
struct BIT
{
    int rt[maxn];
    inline int lowbit(int x) { return x & -x; }

    inline void add(int x)
    {
        for (int i=a[x]; i<=MaxV; i+=lowbit(i)) sgt.Change(rt[i],1,MaxV,Max[x],f[x]);
    }

    inline int ask(int x)
    {
        int ans=0;
        for (int i=Min[x]; i>=1; i-=lowbit(i)) chkMax(ans,sgt.query(rt[i],1,MaxV,1,a[x]));
        return ans;
    }
}bit;

int main()
{
    int n,m;read(n);read(m);
    for (int i=1; i<=n; ++i) read(a[i]), Max[i]=Min[i]=a[i];
    for (int i=1,x,v; i<=m; ++i)
    {
        read(x);read(v);
        chkMax(Max[x],v);
        chkMin(Min[x],v);
    }
    int ans=0;
    for (int i=1; i<=n; ++i)
    {
        f[i]=bit.ask(i)+1;
        chkMax(ans,f[i]);
        bit.add(i);
    }
    write(ans,'\n');
    IO::flush();
    return 0;
}

Guess you like

Origin www.cnblogs.com/G-hsm/p/BZOJ_4553.html