UOJ Logo zhouzixuan的博客

博客

bzoj 1453: [Wc]Dface双面棋盘

2016-01-28 17:24:36 By zhouzixuan
【题目描述】:

【题目解法】:
    炖了狗了!我他妈真是SB的可以啊,居然写了LCT TAT
    我们可以把这道题看成动态加边,动态删边,维护联通块个数的SB模板题
    由于不强制在线,我们维护删除时间的最大生成树,然后就可以实现动态图的问题了
    然后6k+的代码就出来了,他妈让我怎么调啊!
    写了一晚,调了一下午,最后下了数据发现:
    1
    1
    10
    1 1
    1 1
    1 1
    1 1
    1 1
    1 1
    1 1
    1 1
    1 1
    1 1
    卧槽?还有这样的棋盘,日狗!
    然后特判一下就过了,不过跑的飞快!
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <map>
using namespace std;
const int N=305;
const int M=800005;
const int INF=320832080;
const int dx[]={1,0,-1,0};
const int dy[]={0,1,0,-1};
struct node
{
    int x,y; bool flag; //flag=false:cut  flag=true:link
    int del,id_ans,col; bool exist;
} b[M];
struct Node {int son[2],mx,mxid,val,fa; bool lazy;} tree[M+N*N];
int n,m,tot,cnt,a[N][N],ans[M][2],id[N][N];
map<pair<int,int>,int> mp; int ansb,answ,B,W,Tot;
inline long long getint()
{
    long long x=0; char c=getchar(); bool flag=false;
    while ((c!='-')&&((c<'0')||(c>'9'))) c=getchar();
    if (c=='-') flag=true,c=getchar();
    while ((c>='0')&&(c<='9')) x=x*10+(long long)(c-'0'),c=getchar();
    if (flag) return -x; else return x;
}
namespace Graph
{
    bool v[N][N];
    void dfs(int x,int y,int col)
    {
        if (x<1) return; if (x>n) return;
        if (y<1) return; if (y>n) return;
        if (v[x][y]) return; if (a[x][y]!=col) return;
        v[x][y]=true;
        dfs(x-1,y,col); dfs(x+1,y,col);
        dfs(x,y-1,col); dfs(x,y+1,col);
    }
    inline void link(int x,int y)
    {
        if (x>y) swap(x,y); if (mp[make_pair(x,y)]!=0) return;
        ++tot; b[tot].flag=true; b[tot].x=x; b[tot].y=y;
        b[tot].del=INF; mp[make_pair(x,y)]=tot;
    }
    inline void cut(int x,int y)
    {
        if (x>y) swap(x,y); if (mp[make_pair(x,y)]==0) return;
        ++tot; b[tot].flag=false; b[tot].x=x; b[tot].y=y;
        b[mp[make_pair(x,y)]].del=tot;
        b[tot].del=mp[make_pair(x,y)]; mp[make_pair(x,y)]=0;
    }
    void init()
    {
        n=getint(); tot=cnt=0; cnt=n*n;
        for (int i=1; i<=n; i++) for (int j=1; j<=n; j++) a[i][j]=getint();
        for (int i=1; i<=n; i++) for (int j=1; j<=n; j++) id[i][j]=(i-1)*n+j;
        for (int i=1; i<=n; i++)
            for (int j=1; j<=n; j++)
                for (int k=0; k<=3; k++)
                {
                    int x=i+dx[k],y=j+dy[k]; if (id[x][y]==0) continue;
                    if (a[x][y]==a[i][j]) link(id[x][y],id[i][j]),b[tot].col=a[i][j];
                }
        m=getint(); Tot=tot;
        for (int i=1; i<=n; i++)
        for (int j=1; j<=n; j++)
        {
            if (v[i][j]) continue; dfs(i,j,a[i][j]);
            if (a[i][j]==0) W++; else B++;
        }
        for (int i=1; i<=m; i++)
        {
            int x=getint(),y=getint(); a[x][y]=1-a[x][y];
            for (int k=0; k<=3; k++)
            {
                int xx=x+dx[k],yy=y+dy[k]; if (id[xx][yy]==0) continue;
                if (a[x][y]==a[xx][yy]) link(id[x][y],id[xx][yy]);
                if (a[x][y]!=a[xx][yy]) cut(id[x][y],id[xx][yy]);
                if (b[tot].flag) b[tot].col=a[x][y]; else b[tot].col=a[xx][yy];
            }
            b[++tot].id_ans=i; b[tot].x=1-a[x][y]; b[tot].y=a[x][y];
        }
    }
}
namespace LCT
{
    inline void lazy_tag(int p)
    {
        if (tree[p].lazy==false) return;
        int lc=tree[p].son[0],rc=tree[p].son[1];
        if (lc) tree[lc].lazy=!tree[lc].lazy;
        if (rc) tree[rc].lazy=!tree[rc].lazy;
        swap(tree[p].son[0],tree[p].son[1]);
        tree[p].lazy=false;
    }
    inline void updata(int p)
    {
        int lc=tree[p].son[0],rc=tree[p].son[1]; tree[p].mx=tree[p].val; tree[p].mxid=p;
        if (lc) if (tree[lc].mx<tree[p].mx) tree[p].mx=tree[lc].mx,tree[p].mxid=tree[lc].mxid;
        if (rc) if (tree[rc].mx<tree[p].mx) tree[p].mx=tree[rc].mx,tree[p].mxid=tree[rc].mxid;
    }
    inline bool parent(int x,int y)
    {
        if (x==0) return false; if (y==0) return false;
        if (tree[x].son[0]==y) return true;
        if (tree[x].son[1]==y) return true;
        return false;
    }
    inline void rotate(int p,int x)
    {
        int fa=tree[p].fa; lazy_tag(fa); lazy_tag(p);
        tree[fa].son[1-x]=tree[p].son[x]; tree[tree[p].son[x]].fa=fa;
        if (tree[fa].fa)
        {
            if (fa==tree[tree[fa].fa].son[0]) tree[tree[fa].fa].son[0]=p;
            if (fa==tree[tree[fa].fa].son[1]) tree[tree[fa].fa].son[1]=p;
        }
        tree[p].fa=tree[fa].fa; tree[p].son[x]=fa; tree[fa].fa=p;
        updata(fa); updata(p);
    }
    inline void splay(int p)
    {
        lazy_tag(tree[p].fa); lazy_tag(p);
        while (true)
        {
            int j=tree[p].fa,i=tree[j].fa;
            if (!parent(j,p)) break;
            if (!parent(i,j))
            {
                lazy_tag(j); lazy_tag(p);
                if (p==tree[j].son[0]) rotate(p,1); else rotate(p,0); continue;
            }
            lazy_tag(i); lazy_tag(j); lazy_tag(p);
            if (j==tree[i].son[0])
            {
                if (p==tree[j].son[0]) rotate(j,1),rotate(p,1);
                else rotate(p,0),rotate(p,1);
            }
            else
            {
                if (p==tree[j].son[1]) rotate(j,0),rotate(p,0);
                else rotate(p,1),rotate(p,0);
            }
        }
    }
    inline int Access(int p)
    {
        int x=0;
        while (p)
        {
            splay(p); tree[p].son[1]=x;
            updata(p); x=p; p=tree[p].fa;
        }
        return x;
    }
    inline int getroot(int p)
    {
        Access(p); splay(p);
        while (true)
        {
            lazy_tag(p);
            if (tree[p].son[0]==0) return p;
            p=tree[p].son[0];
        }
        return 0;
    }
    inline void makeroot(int p)
    {
        Access(p); splay(p);
        tree[p].lazy=!tree[p].lazy;
    }
    inline void link(int x,int y)
    {
        makeroot(x); splay(x);
        tree[x].fa=y;
    }
    inline void cut(int x,int y)
    {
        makeroot(x); Access(y); splay(y);
        tree[tree[y].son[0]].fa=0; tree[y].son[0]=0;
    }
    inline void link(int p)
    {
        int x=b[p].x,y=b[p].y;
        if (getroot(x)==getroot(y))
        {
            makeroot(x); Access(y); splay(y);
            if (b[p].del<=tree[y].mx) {b[p].exist=false; return;}
            int id=tree[y].mxid-cnt; b[id].exist=false;
            cut(id+cnt,b[id].x); cut(id+cnt,b[id].y);
            if (b[p].col==0) answ++; else ansb++;
        }
        tree[p+cnt].val=b[p].del; updata(p+cnt); b[p].exist=true;
        link(p+cnt,b[p].x); link(p+cnt,b[p].y);
        if (b[p].col==0) answ--; else ansb--;
    }
    inline void cut(int p)
    {
        int id=b[p].del; if (!b[id].exist) return;
        cut(id+cnt,b[p].x); cut(id+cnt,b[p].y);
        if (b[p].col==0) answ++; else ansb++;
    }
    void solve()
    {
        if (n==1)
        {
            for (int i=1; i<=m; i++) printf("%d %d\n",1-i%2,i%2);
            return;
        }
        for (int i=1; i<=cnt; i++) tree[i].val=INF+INF,updata(i);
        for (int i=1; i<=tot; i++)
        {
            if ((b[i].flag)&&(b[i].id_ans==0)) link(i);
            if ((!b[i].flag)&&(b[i].id_ans==0)) cut(i);
            if ((b[i].id_ans!=0)&&(n!=1))
            {
                if (b[i].x==0) answ--; else ansb--;
                if (b[i].y==0) answ++; else ansb++;
            }
            if (b[i].id_ans!=0) ans[b[i].id_ans][0]=ansb,ans[b[i].id_ans][1]=answ;
            if (i==Tot) answ=W,ansb=B;
        }
        for (int i=1; i<=m; i++) printf("%d %d\n",ans[i][0],ans[i][1]);
    }
}
int main()
{
    Graph::init();
    LCT::solve();
    return 0;
}

评论

暂无评论

发表评论

可以用@mike来提到mike这个用户,mike会被高亮显示。如果你真的想打“@”这个字符,请用“@@”。