• [IOI2018] seats 排座位


    [IOI2018] seats 排座位 

    IOI2018题解

    压缩状态思想很不错的

    每次把原来的贡献减掉,新来的再加上

    最多涉及10个点

    注意:

    1.去重

    2.下标从0开始

    3.线段树初始的最小值个数都是r-l+1

    代码:

    #include<bits/stdc++.h>
    #define reg register int
    #define il inline
    #define mid ((l+r)>>1)
    #define numb (ch^'0')
    using namespace std;
    typedef long long ll;
    il void rd(int &x){
        char ch;x=0;bool fl=false;
        while(!isdigit(ch=getchar()))(ch=='-')&&(fl=true);
        for(x=numb;isdigit(ch=getchar());x=x*10+numb);
        (fl==true)&&(x=-x);
    }
    namespace Miracle{
    const int N=1000000+5;
    const int inf=0x3f3f3f3f;
    int id[N],vis[N],sta[N],top;
    int pos[N][2];
    int n,m,q;
    int num(int x,int y){
        return (x-1)*m+y;
    }
    struct tr{
        int mi,cnt;
        int mx;
        int ad;
    }t[4*N];
    void pushup(int x){
        t[x].mi=min(t[x<<1].mi,t[x<<1|1].mi);
        t[x].mx=max(t[x<<1].mx,t[x<<1|1].mx);
        t[x].cnt=t[x<<1].cnt*(t[x<<1].mi==t[x].mi)+t[x<<1|1].cnt*(t[x<<1|1].mi==t[x].mi);
    }
    void pushdown(int x){
        if(!t[x].ad) return;
        t[x<<1].ad+=t[x].ad;
        t[x<<1].mi+=t[x].ad;
        t[x<<1].mx+=t[x].ad;
        t[x<<1|1].ad+=t[x].ad;
        t[x<<1|1].mi+=t[x].ad;
        t[x<<1|1].mx+=t[x].ad;
        
        t[x].ad=0;
    }
    void build(int x,int l,int r){
        if(l==r){
            t[x].cnt=1;return;
        }
        build(x<<1,l,mid);
        build(x<<1|1,mid+1,r);
        pushup(x);
    }
    void add(int x,int l,int r,int L,int R,int c){
        if(L<=l&&r<=R){
            t[x].ad+=c;
            t[x].mi+=c;
            t[x].mx+=c;
            if(t[x].mi==t[x].mx) t[x].cnt=r-l+1;
            return;
        }    
        pushdown(x);
        if(L<=mid) add(x<<1,l,mid,L,R,c);
        if(mid<R) add(x<<1|1,mid+1,r,L,R,c);
        pushup(x);
    }
    int mv[4][2]={{+1,0},{-1,0},{0,+1},{0,-1}};
    void wrk1(int x,int y,int c){
        //cout<<" x y "<<x<<" "<<y<<" c "<<c<<endl;
        int mi=inf,cmi=inf;
        for(reg i=0;i<4;++i){
            int dx=x+mv[i][0],dy=y+mv[i][1];
            if(dx>=1&&dx<=n&&dy>=1&&dy<=m){
                if(id[num(dx,dy)]<mi){
                    cmi=mi;mi=id[num(dx,dy)];
                }else cmi=min(cmi,id[num(dx,dy)]);
            }
        }
        
        if(cmi<=id[num(x,y)]-1) {
            //cout<<" x y "<<x<<" "<<y<<" : "<<mi<<" "<<cmi<<endl;
            add(1,1,n*m,cmi,id[num(x,y)]-1,c);
        }
    }
    void wrk2(int x,int y,int c){
        int mi=n*m+1;
        int dx=x-1,dy=y;
        if(dx>=1&&dx<=n&&dy>=1&&dy<=m){
            mi=min(mi,id[num(dx,dy)]);
        }
        dx=x,dy=y-1;
        if(dx>=1&&dx<=n&&dy>=1&&dy<=m){
            mi=min(mi,id[num(dx,dy)]);
        }
        //cout<<" x y "<<x<<" "<<y<<" mimimi "<<mi<<endl;
        if(id[num(x,y)]<=mi-1) add(1,1,n*m,id[num(x,y)],mi-1,c);
    }
    void sol(int x,int y,int c){
        //cout<<" sol "<<x<<" "<<y<<" c "<<c<<endl;
        if(!vis[num(x,y)]) {
            sta[++top]=num(x,y);
            vis[num(x,y)]=1;
            wrk1(x,y,c);wrk2(x,y,c);
        }
        for(reg i=0;i<4;++i){
            int dx=x+mv[i][0],dy=y+mv[i][1];
            if(dx>=1&&dx<=n&&dy>=1&&dy<=m&&!vis[num(dx,dy)]){
                vis[num(dx,dy)]=1;
                sta[++top]=num(dx,dy);
                wrk1(dx,dy,c);wrk2(dx,dy,c);
            }
        }
    }
    int main(){
        rd(n);rd(m);rd(q);
        build(1,1,n*m);
        int x,y;
        for(reg i=1;i<=n*m;++i){
            rd(x);rd(y);
            ++x;++y;
            pos[i][0]=x;pos[i][1]=y;
            id[num(x,y)]=i;
        }
        for(reg i=1;i<=n;++i){
            for(reg j=1;j<=m;++j){
                wrk1(i,j,1);
                wrk2(i,j,1);
            }
        }
        //cout<<t[1].mi<<" "<<t[1].mx<<" "<<t[1].cnt<<endl;
        int A,B;
        while(q--){
            rd(A);rd(B);        
            ++A;++B;
            top=0;
            
            x=pos[A][0],y=pos[A][1];
            sol(x,y,-1);
            x=pos[B][0],y=pos[B][1];
            sol(x,y,-1);
            
            while(top) vis[sta[top--]]=0;
            swap(id[num(pos[A][0],pos[A][1])],id[num(pos[B][0],pos[B][1])]);
            swap(pos[A][0],pos[B][0]);
            swap(pos[A][1],pos[B][1]);
            
            x=pos[A][0],y=pos[A][1];
            sol(x,y,1);
            x=pos[B][0],y=pos[B][1];
            sol(x,y,1);
            
            while(top) vis[sta[top--]]=0;
            
            int ans=0;
            if(t[1].mi==1) ans=t[1].cnt;
            printf("%d
    ",ans);
        }
        return 0;
    }
    
    }
    signed main(){
        Miracle::main();
        return 0;
    }
    
    /*
       Author: *Miracle*
       Date: 2019/2/10 17:53:31
    */
  • 相关阅读:
    linux基础知识
    linux运维指令
    redis的三种集群方式
    docker安装tomcat
    cetos7.7安装docker
    Redis和MySQL数据一致中出现的几种情况
    外行人都能看懂的 Spring Cloud,错过了血亏!
    交换机和猫、路由器到底有什么区别
    一次给女朋友转账引发我对分布式事务的思考
    sql merge
  • 原文地址:https://www.cnblogs.com/Miracevin/p/10360146.html
Copyright © 2020-2023  润新知