CF878C,图论与数据结构

当时赛场上读错题+被同学带偏节奏,在想kd-tree,然后gg。
首先,可以根据选手与选手之间直接比赛的胜负关系,可以建出一
张有向图。考虑将这张图进行SCC缩点,缩完后的DAG一定是一条链,这是一个良好的性质。
然后加入点的时候,就在 k 个维度上找出它的前驱 p 和后继 s ,然后如果在原有的链中, s p 的前面,那么可以将 p s 之间的强联通分量缩起来。具体操作的时候,我用了k棵set维护k个维度上的前驱后继,一棵treap维护缩点后的链,然后就终于可以用上9月封装的那个模板了。至于为什么不用手写treap代替那k棵set呢?那篇博客里说过了这个版本的treap跑不过stl的set,我好菜啊
最后复杂度是 O(nk2logn) ,不过很不满,而且这是在线的,可能比std的离线(好像是的,虽然我没看懂)多个k。然而我多了个k,好像运行时间不到别人程序的两倍,所以 k<2 ?手动滑稽

#include
namespace GenHelper
{
    unsigned z1,z2,z3,z4,b;
    unsigned rand_()
    {
    b=((z1<<6)^z1)>>13;
    z1=((z1&4294967294U)<<18)^b;
    b=((z2<<2)^z2)>>27;
    z2=((z2&4294967288U)<<2)^b;
    b=((z3<<13)^z3)>>21;
    z3=((z3&4294967280U)<<7)^b;
    b=((z4<<3)^z4)>>12;
    z4=((z4&4294967168U)<<13)^b;
    return (z1^z2^z3^z4);
    }
}
void srand(unsigned x)
{using namespace GenHelper;
z1=x; z2=(~x)^0x233333333U; z3=x^0x1234598766U; z4=(~x)+51;}
int rand()
{
    using namespace GenHelper;
    int a=rand_()&32767;
    int b=rand_()&32767;
    return a*32768+b;
}
template<typename T> class treap{
    private:
        struct node{
            node*l,*r,*a[2];
            int p,size,w;
            T v;
            node(T _v):v(_v){l=r=a[0]=a[1]=NULL,p=rand(),w=size=1;}
            void maintain(){size=w+(l?l->size:0)+(r?r->size:0);}
        };
        node*head,*mi;
        void lturn(node* &x){
            node*t=x->r;
            x->r=t->l;
            t->l=x;
            x->maintain();
            t->maintain();
            x=t;
        }
        void rturn(node* &x){
            node*t=x->l;
            x->l=t->r;
            t->r=x;
            x->maintain();
            t->maintain();
            x=t;
        }
        void ins(node* &o,T y,node*fa,int v){
            if(o==NULL){
                o=new node(y);
                o->a[v^1]=fa;
                o->a[v]=fa->a[v];
                if(fa->a[v])fa->a[v]->a[v^1]=o;
                fa->a[v]=o;
            }else if(y>o->v){
                ins(o->r,y,o,1);
                if(o->r->p>o->p)lturn(o);
            }else if(yv){
                ins(o->l,y,o,0);
                if(o->l->p>o->p)rturn(o);
            }else ++o->w;
            o->maintain();
        }
        void del(node* &x,T y){
            if(x==NULL)return;
            if(y>x->v)del(x->r,y);
                else if(yv)del(x->l,y);
                    else{
                        if(x->w>1){
                            --x->size;
                            --x->w;
                            return;
                        }
                        if(x->l==NULL){
                            node*z=x;
                            if(x->a[0])x->a[0]->a[1]=x->a[1];
                            if(x->a[1])x->a[1]->a[0]=x->a[0];
                            x=x->r;
                            delete z;
                            return;
                        }
                        if(x->r==NULL){
                            node*z=x;
                            if(x->a[0])x->a[0]->a[1]=x->a[1];
                            if(x->a[1])x->a[1]->a[0]=x->a[0];
                            x=x->l;
                            delete z;
                            return;
                        }
                        if(x->l->p>x->r->p){                                        
                            rturn(x);
                            del(x->r,y);
                        }else{
                            lturn(x);
                            del(x->l,y);
                        }
                    }
            if(x!=NULL)--x->size;
        }
    public:
        struct iterator{
            node* x;
            iterator(node*_x=NULL):x(_x){}
            bool operator!=(const iterator&rhs)const{return x!=rhs.x;}
            bool operator==(const iterator&rhs)const{return x==rhs.x;}
            T operator*(){return x->v;}
            iterator operator++(){return x=x->a[1];}
            iterator operator++(int){static node*t;t=x;x=x->a[1];return t;}
            iterator operator--(){return x=x->a[0];}
            iterator operator--(int){static node*t;t=x;x=x->a[0];return t;}
        };

        treap(){srand(19260817);}
        inline void insert(T x){
            if(head==NULL)mi=head=new node(x);
                else ins(head,x,NULL,0),mi=mi->a[0]?mi->a[0]:mi;
        }
        inline void erase(T x){
            mi=mi->v==x && mi->w==1?mi->a[1]:mi;del(head,x);
        }
        inline void erase(iterator x){
            erase(*x);
        }
        inline int rank(T y){
            register node*x=head;
            register int ans=0,s;
            while(x!=NULL){
                s=x->l?x->l->size:0;
                if(y==x->v)return ans+s+1;
                if(y>x->v){
                    ans+=s+x->w;
                    x=x->r;
                }else x=x->l;
            }
            return ans+1;
        }
        inline T kth(T y){
            register node*x=head;
            register int u,v;
            for(;;){
                u=x->l?x->l->size:0,v=x->w;
                if(u=y)return x->v;
                if(y>u+v){
                    x=x->r;
                    y-=u+v;
                }else x=x->l;
            }
        }
        inline iterator prec(T y){
            node*x=head,*t=NULL;
            while(x!=NULL){
                if(x->v>=y)x=x->l;
                    else{
                        t=x;
                        x=x->r;
                    }
            }     
            return t;
        }
        inline iterator succ(T y){
            node*x=head,*t=NULL;
            while(x)
                if(x->v<=y)x=x->r;
                    else{
                        t=x;
                        x=x->l;
                    }
            return t;
        }
        inline iterator find(T v){
            register node*x=head;
            for(;x && x->v!=v;x=vv?x->l:x->r);
            return x;
        }
        inline int count(T v){
            register iterator t=find(v);return t.x?t.x->w:0;
        }
        inline iterator begin(){return mi;}
        inline iterator end(){return NULL;}
};
const int N=50005;
int sz[N],f[N],n,i,k,a[N][12],j,b[12],c[12],l;
struct node{
    int i,x;
    node(int _i=0,int _x=1):i(_i),x(_x){}
    inline bool operator==(const node&rhs)const{return i==rhs.i;}
    inline bool operator!=(const node&rhs)const{return i!=rhs.i;}
    inline bool operator<(const node&rhs)const{return a[i][x]inline bool operator>(const node&rhs)const{return a[i][x]>a[rhs.i][rhs.x];}
};
treap t;
treap::iterator it,en;
std::set s[12];
std::set::iterator it1,it2;
inline int gfa(int x){return f[x]==x?x:f[x]=gfa(f[x]);}
inline void un(int x,int y){x=gfa(x),y=gfa(y);if(x!=y)f[x]=y,sz[y]+=sz[x];}
inline bool cmp(int x,int y){static int i;for(i=1;i<=k;++i)if(a[x][i]>=a[y][i])return 1;return 0;}
int main(){
    scanf("%d%d",&n,&k);
    for(i=1;i<=n;++i){*b=*c=0;
        f[i]=i,sz[i]=1;for(j=1;j<=k;++j){
            scanf("%d",a[i]+j);
            it1=s[j].upper_bound((node){i,j}),it2=it1;
            if(it1!=s[j].begin())b[++*b]=(--it1)->i;
            if(it2!=s[j].end())c[++*c]=it2->i;s[j].insert((node){i,j});
        }
        //printf("%d\n",t.count(3));
        for(j=1;j<=*b;++j)
            for(l=1;l<=*c;++l){
                b[j]=gfa(b[j]),c[l]=gfa(c[l]);
                if(b[j]==c[l] || t.rank(b[j])>t.rank(c[l])){
                    for(it=t.find(c[l]),en=t.find(b[j]);it!=en;)
                        un((*it).i,b[j]),t.erase(it++);
                    un(i,b[j]);
                }
            }
        if(f[i]==i)t.insert(i);
        printf("%d\n",sz[gfa(s[1].rbegin()->i)]);
    }
    return 0;
}

你可能感兴趣的:(CF878C,图论与数据结构)