[2019.8.6] T3 Cixi simulation game set (SET) (segment tree DP)

Segment tree \ (the DP \)

First we found that each number is certainly to his predecessor or successor even the edges.

We open a weight of the segment tree, wherein each node a record \ (F_ {0 / 1,0 /. 1} \) , this interval represents the left and right end points are connected through the case side, so that the interval in line with the minimum cost criteria.

Consider if the left point right point left or right son's son has not even had the edge when a merger, it must be connected to the side, or not even the edges.

Then I compare the wording stupid, I do not know why you need special treatment when the judge about his son in a node is only a number.

The last answer is the root node \ (F_ {1, 1} \) .

See specific code.

Code

#include<bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define Reg register
#define RI Reg int
#define Con const
#define CI Con int&
#define I inline
#define W while
#define N 200000
#define V 1000000000
#define LV 30
#define LL long long
#define INF 1e18
#define min(x,y) ((x)<(y)?(x):(y))
#define Gmin(x,y) (x>(y)&&(x=(y)))
using namespace std;
int n,Qt,a[2*N+5];
class FastIO
{
    private:
        #define FS 100000
        #define tc() (A==B&&(B=(A=FI)+fread(FI,1,FS,stdin),A==B)?EOF:*A++)
        #define pc(c) (C==E&&(clear(),0),*C++=c)
        #define tn (x<<3)+(x<<1)
        #define D isdigit(c=tc())
        int T;char c,*A,*B,*C,*E,FI[FS],FO[FS],S[FS];
    public:
        I FastIO() {A=B=FI,C=FO,E=FO+FS;}
        Tp I void read(Ty& x) {x=0;W(!D);W(x=tn+(c&15),D);}
        Tp I void write(Ty x) {W(S[++T]=x%10+48,x/=10);W(T) pc(S[T--]);}
        Tp I void writeln(Con Ty& x) {write(x),pc('\n');}
        I void clear() {fwrite(FO,1,C-FO,stdout),C=FO;}
        #undef D
}F;
class SegmentTreeSolver
{
    private:
        template<int SZ> class SegmentTree//线段树
        {
            private:
                #define F5(x,l,r)\
                    O[x].f[l][r]=O[O[x].S[0]].f[l][1]+O[O[x].S[1]].f[1][r],\
                    Gmin(O[x].f[l][r],O[O[x].S[0]].f[l][0]+O[O[x].S[1]].f[0][r]+O[O[x].S[1]].L-O[O[x].S[0]].R),\
                    Gmin(O[x].f[l][r],O[O[x].S[0]].f[l][0]+O[O[x].S[1]].f[1][r]+O[O[x].S[1]].L-O[O[x].S[0]].R),\
                    Gmin(O[x].f[l][r],O[O[x].S[0]].f[l][1]+O[O[x].S[1]].f[0][r]+O[O[x].S[1]].L-O[O[x].S[0]].R)//普通情况下转移
                int n,rt,Nt;struct node//维护节点信息
                {
                    int Ex,L,R,S[2];LL f[2][2];
                    I node(CI x=0):Ex(0),L(x),R(x),S({0,0}),f({{0,INF},{INF,INF}}){}
                    I void operator = (Con node& o)
                    {
                        Ex=o.Ex,L=o.L,R=o.R,f[0][0]=o.f[0][0],f[0][1]=o.f[0][1],
                        f[1][0]=o.f[1][0],f[1][1]=o.f[1][1];
                    }
                }O[SZ+5];
                I void PU(CI x)//上传信息
                {
                    if(!O[O[x].S[0]].Ex) return (void)(O[x]=O[O[x].S[1]]);//如果没有左儿子
                    if(!O[O[x].S[1]].Ex) return (void)(O[x]=O[O[x].S[0]]);//如果没有右儿子
                    O[x].Ex=1,O[x].L=O[O[x].S[0]].L,O[x].R=O[O[x].S[1]].R;//上传基础信息
                    if(O[O[x].S[0]].L==O[O[x].S[0]].R&&O[O[x].S[1]].L==O[O[x].S[1]].R)//合并两个单点
                    {
                        O[x].f[0][0]=0,O[x].f[1][1]=O[O[x].S[1]].L-O[O[x].S[0]].R,
                        O[x].f[0][1]=O[x].f[1][0]=INF;return;
                    }
                    if(O[O[x].S[0]].L==O[O[x].S[0]].R)//合并单点和区间
                    {
                        O[x].f[1][0]=min(O[O[x].S[1]].f[0][0],O[O[x].S[1]].f[1][0])+O[O[x].S[1]].L-O[O[x].S[0]].R,
                        O[x].f[1][1]=min(O[O[x].S[1]].f[0][1],O[O[x].S[1]].f[1][1])+O[O[x].S[1]].L-O[O[x].S[0]].R,
                        O[x].f[0][0]=O[O[x].S[1]].f[1][0],O[x].f[0][1]=O[O[x].S[1]].f[1][1];return;
                    }
                    if(O[O[x].S[1]].L==O[O[x].S[1]].R)//合并区间和单点
                    {
                        O[x].f[0][1]=min(O[O[x].S[0]].f[0][0],O[O[x].S[0]].f[0][1])+O[O[x].S[1]].L-O[O[x].S[0]].R,
                        O[x].f[1][1]=min(O[O[x].S[0]].f[1][0],O[O[x].S[0]].f[1][1])+O[O[x].S[1]].L-O[O[x].S[0]].R,
                        O[x].f[0][0]=O[O[x].S[0]].f[0][1],O[x].f[1][0]=O[O[x].S[0]].f[1][1];return;
                    }
                    F5(x,0,0),F5(x,0,1),F5(x,1,0),F5(x,1,1);
                }
                I void Upt(CI x,CI v,CI l,CI r,int& rt)//单点修改
                {
                    if(!rt&&(rt=++Nt),l==r) return (void)(!O[rt].Ex&&(O[rt]=node(l),0),O[rt].Ex+=v);
                    RI mid=l+r>>1;x<=mid?Upt(x,v,l,mid,O[rt].S[0]):Upt(x,v,mid+1,r,O[rt].S[1]),PU(rt);
                }
            public:
                I void Init(CI _n) {n=_n;}I void Upt(CI x,CI v) {Upt(x,v,1,n,rt);}
                I LL Qry() {return O[rt].f[1][1];}//询问
        };SegmentTree<N*LV> S;
    public:
        I void Solve()
        {
            RI i,op,x;for(S.Init(V),i=1;i<=n;++i) S.Upt(a[i],1);//初始化
            W(Qt--) F.read(op),F.read(x),S.Upt(x,op==1?1:-1),F.writeln(S.Qry());//处理操作
        }
}S;
int main()
{
    freopen("set.in","r",stdin),freopen("set.out","w",stdout);
    RI i;for(F.read(n),F.read(Qt),i=1;i<=n;++i) F.read(a[i]);
    return sort(a+1,a+n+1),S.Solve(),F.clear(),0;
}

Guess you like

Origin www.cnblogs.com/chenxiaoran666/p/Contest20190806T3.html