【WC2005】【BZOJ1453】Dface双面棋盘

Description
这里写图片描述
Input
这里写图片描述
Output
这里写图片描述
Sample Input
这里写图片描述
Sample Output
这里写图片描述
HINT
这里写图片描述
Source

动态图问题(和徐寅展讲的不一样,这个事可以离线的)
LCT维护删除时间的最大生成树,和4025一个姿势
注意Cut时候判断一下是不是要更改答案
我的LCT因为姿势不优美一开始MLE了

蟹蟹雅礼中学的Dashgua君帮我改了改姿势QwQ

AC code↓

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#define MAXN 40100
#define SIZE 210
#define GET (ch>='0'&&ch<='9')
using namespace std;
int n,m,top,Top;
int ans[3];
int sta[MAXN*3],T;
int a[SIZE][SIZE];
int dx[5]={0,0,0,1,-1},dy[5]={0,1,-1,0,0};
void in(int &x)
{
    char ch=getchar();x=0;
    while (!GET)    ch=getchar();
    while (GET) x=x*10+ch-'0',ch=getchar();
}
const int poolsize = 200020;
int poolv[poolsize], next[poolsize], pind;
struct edge
{
    int u,v;
    struct queue
    {
      int head, tail;
      int front()
      {
           return poolv[head];
      }
      void push(int v)
      {
           poolv[++pind] = v, next[tail] = pind, tail = pind;
           if(head == 0) head = pind;
      }
      void pop()
      {
           head = next[head];
      }
    } w;
}e[MAXN*3];
struct splay
{
    int ch[2],fa,st;
    bool rev;
}tree[MAXN*3];
int num(int x,int y)    {return x*n-n+y;}
void insert(int u,int v)    
{
    e[++top].u=u;e[top].v=v;tree[top].st=top;
}
bool is_root(int x) {return tree[tree[x].fa].ch[0]!=x&&tree[tree[x].fa].ch[1]!=x;}
void push_down(int x)
{
    if (tree[x].rev)
    {
        tree[tree[x].ch[0]].rev^=1;tree[tree[x].ch[1]].rev^=1;
        swap(tree[x].ch[0],tree[x].ch[1]);
    }
    tree[x].rev=0;
}
void push_up(int x)
{
    int l=tree[x].ch[0],r=tree[x].ch[1];tree[x].st=x;
    if (l&&e[tree[l].st].w.front()<e[tree[x].st].w.front()) tree[x].st=tree[l].st;
    if (r&&e[tree[r].st].w.front()<e[tree[x].st].w.front()) tree[x].st=tree[r].st;
}
void rot(int x)
{
    int y=tree[x].fa,z=tree[y].fa,l,r;
    l=(tree[y].ch[1]==x);r=l^1;
    if (!is_root(y))    tree[z].ch[tree[z].ch[1]==y]=x;
    tree[x].fa=z;tree[y].fa=x;tree[tree[x].ch[r]].fa=y;
    tree[y].ch[l]=tree[x].ch[r];tree[x].ch[r]=y;
    push_up(y);push_up(x);
}
void Splay(int x)
{
    sta[++T]=x;
    for (int i=x;!is_root(i);i=tree[i].fa)  sta[++T]=tree[i].fa;
    while (T)   push_down(sta[T--]);
    while (!is_root(x))
    {
        int y=tree[x].fa,z=tree[y].fa;
        if (!is_root(y))
        {
            if ((tree[z].ch[0]==y)^(tree[y].ch[0]==x))  rot(x);
            else    rot(y);
        }
        rot(x);
    }
}
void access(int x)
{
    for (int i=0;x;i=x,x=tree[x].fa)    Splay(x),tree[x].ch[1]=i,push_up(x);
}
void make_root(int x)
{
    access(x);Splay(x);tree[x].rev^=1;
}
void link(int x,int y)
{
    make_root(x);tree[x].fa=y;
}
/*void cut(int x,int y)
{
    make_root(x);access(y);Splay(y);tree[y].ch[0]=tree[x].fa=0;push_up(y);
}*/
bool cut(int x,int y)
{
    make_root(x);access(y);Splay(y);
    if (tree[y].ch[0]!=x||tree[x].ch[1]!=0) return 0;
    tree[y].ch[0]=tree[x].fa=0;push_up(y);return 1;
}
void split(int x,int y)
{
    make_root(x);access(y);Splay(y);
}
int find(int x)
{
    access(x);Splay(x);
    for (;tree[x].ch[0];x=tree[x].ch[0]);
    return x;
}
void add(int x,int col)
{
    int u=e[x].u,v=e[x].v;
    if (find(u)!=find(v))   link(u,x),link(v,x),ans[col]--;
    else
    {
        split(u,v);int y=tree[v].st;
        if (e[y].w.front()<e[x].w.front())
            cut(e[y].u,y),cut(e[y].v,y),link(e[x].u,x),link(e[x].v,x);
    }
}
void del(int x,int col)
{
    int u=e[x].u,v=e[x].v;
    if (cut(x,u)&&cut(x,v)) ans[col]++;
    e[x].w.pop();
}
struct Query    {short x,y;}q[10010];
bool in_size(int x,int y)   {return !(x<=0||y<=0||x>n||y>n);}
int main()
{
    in(n);int x,y;
    for (int i=1;i<=n*n;i++)    insert(0,0),e[top].w.push(10010);
    for (int i=1;i<=n;i++)
        for (int j=1;j<=n;j++)  in(a[i][j]),tree[num(i,j)].st=Top;
    for (int i=1;i<=n;i++)
        for (int j=1;j<=n;j++)  insert(num(i,j),num(i,j+1));
    for (int i=1;i<=n;i++)
        for (int j=1;j<=n;j++)  insert(num(i,j),num(i+1,j));
    in(m);
    for (int i=1;i<=m;i++)
    {
        in(x);in(y);q[i]=(Query){(short)x,(short)y};
        for (int j=1;j<=4;j++)
        {
            int tx=x+dx[j],ty=y+dy[j];
            if (!in_size(tx,ty))    continue;
            if (a[x][y]==a[tx][ty])
                e[min(num(x,y),num(tx,ty))+(((j-1)>>1)+1)*n*n].w.push(i);
        }
        a[x][y]^=1;
    }
    for (int i=1;i<=n;i++)
        for (int j=1;j<=n;j++)
        {
            int tx=i,ty=j+1;
            if (in_size(tx,ty)&&a[i][j]==a[tx][ty]) e[num(i,j)+n*n].w.push(m+1);
            tx=i+1;ty=j;
            if (in_size(tx,ty)&&a[i][j]==a[tx][ty]) e[num(i,j)+(n*n<<1)].w.push(m+1);
        }
    for (int i=m;i;i--) a[q[i].x][q[i].y]^=1;
    for (int i=1;i<=n;i++)
        for (int j=1;j<=n;j++)  ans[a[i][j]]++;
    int cnt=0;
    for (int i=1;i<=n;i++)
        for (int j=1;j<=n;j++)
        {
            int tx=i,ty=j+1;
            if (in_size(tx,ty)&&a[i][j]==a[tx][ty]) add(num(i,j)+n*n,a[i][j]),cnt++;
            tx=i+1;ty=j;
            if (in_size(tx,ty)&&a[i][j]==a[tx][ty]) add(num(i,j)+(n*n<<1),a[i][j]),cnt++;
        }
    for (int i=1;i<=m;i++)
    {
        x=q[i].x;y=q[i].y;
        for (int j=1;j<=4;j++)
        {
            int tx=x+dx[j],ty=y+dy[j];
            if (in_size(tx,ty)&&a[x][y]==a[tx][ty]) 
                del(min(num(x,y),num(tx,ty))+(((j-1)>>1)+1)*n*n,a[x][y]);
        }
        ans[a[x][y]]--;a[x][y]^=1;ans[a[x][y]]++;
        for (int j=1;j<=4;j++)
        {
            int tx=x+dx[j],ty=y+dy[j];
            if (in_size(tx,ty)&&a[x][y]==a[tx][ty]) 
                add(min(num(x,y),num(tx,ty))+(((j-1)>>1)+1)*n*n,a[x][y]);
        }
        printf("%d %d\n",ans[1],ans[0]);
    }
}

MLE code↓

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#define MAXN 40100
#define SIZE 210
#define GET (ch>='0'&&ch<='9')
using namespace std;
int n,m,top,Top;
int ans[3];
int sta[MAXN*3],T;
int a[SIZE][SIZE];
int dx[5]={0,0,0,1,-1},dy[5]={0,1,-1,0,0};
void in(int &x)
{
    char ch=getchar();x=0;
    while (!GET)    ch=getchar();
    while (GET) x=x*10+ch-'0',ch=getchar();
}
struct edge
{
    int u,v;
    queue<short> w;
}e[MAXN*3];
struct splay
{
    int ch[2],fa,st;
    bool rev;
}tree[MAXN*3];
int num(int x,int y)    {return x*n-n+y;}
void insert(int u,int v)    
{
    e[++top].u=u;e[top].v=v;tree[top].st=top;
}
bool is_root(int x) {return tree[tree[x].fa].ch[0]!=x&&tree[tree[x].fa].ch[1]!=x;}
void push_down(int x)
{
    if (tree[x].rev)
    {
        tree[tree[x].ch[0]].rev^=1;tree[tree[x].ch[1]].rev^=1;
        swap(tree[x].ch[0],tree[x].ch[1]);
    }
    tree[x].rev=0;
}
void push_up(int x)
{
    int l=tree[x].ch[0],r=tree[x].ch[1];tree[x].st=x;
    if (l&&e[tree[l].st].w.front()<e[tree[x].st].w.front()) tree[x].st=tree[l].st;
    if (r&&e[tree[r].st].w.front()<e[tree[x].st].w.front()) tree[x].st=tree[r].st;
}
void rot(int x)
{
    int y=tree[x].fa,z=tree[y].fa,l,r;
    l=(tree[y].ch[1]==x);r=l^1;
    if (!is_root(y))    tree[z].ch[tree[z].ch[1]==y]=x;
    tree[x].fa=z;tree[y].fa=x;tree[tree[x].ch[r]].fa=y;
    tree[y].ch[l]=tree[x].ch[r];tree[x].ch[r]=y;
    push_up(y);push_up(x);
}
void Splay(int x)
{
    sta[++T]=x;
    for (int i=x;!is_root(i);i=tree[i].fa)  sta[++T]=tree[i].fa;
    while (T)   push_down(sta[T--]);
    while (!is_root(x))
    {
        int y=tree[x].fa,z=tree[y].fa;
        if (!is_root(y))
        {
            if ((tree[z].ch[0]==y)^(tree[y].ch[0]==x))  rot(x);
            else    rot(y);
        }
        rot(x);
    }
}
void access(int x)
{
    for (int i=0;x;i=x,x=tree[x].fa)    Splay(x),tree[x].ch[1]=i,push_up(x);
}
void make_root(int x)
{
    access(x);Splay(x);tree[x].rev^=1;
}
void link(int x,int y)
{
    make_root(x);tree[x].fa=y;
}
/*void cut(int x,int y)
{
    make_root(x);access(y);Splay(y);tree[y].ch[0]=tree[x].fa=0;push_up(y);
}*/
bool cut(int x,int y)
{
    make_root(x);access(y);Splay(y);
    if (tree[y].ch[0]!=x||tree[x].ch[1]!=0) return 0;
    tree[y].ch[0]=tree[x].fa=0;push_up(y);return 1;
}
void split(int x,int y)
{
    make_root(x);access(y);Splay(y);
}
int find(int x)
{
    access(x);Splay(x);
    for (;tree[x].ch[0];x=tree[x].ch[0]);
    return x;
}
void add(int x,int col)
{
    int u=e[x].u,v=e[x].v;
    if (find(u)!=find(v))   link(u,x),link(v,x),ans[col]--;
    else
    {
        split(u,v);int y=tree[v].st;
        if (e[y].w.front()<e[x].w.front())
            cut(e[y].u,y),cut(e[y].v,y),link(e[x].u,x),link(e[x].v,x);
    }
}
void del(int x,int col)
{
    int u=e[x].u,v=e[x].v;
    if (cut(x,u)&&cut(x,v)) ans[col]++;
    e[x].w.pop();
}
struct Query    {short x,y;}q[10010];
bool in_size(int x,int y)   {return !(x<=0||y<=0||x>n||y>n);}
int main()
{
    in(n);int x,y;
    for (int i=1;i<=n*n;i++)    insert(0,0),e[top].w.push(10010);
    for (int i=1;i<=n;i++)
        for (int j=1;j<=n;j++)  in(a[i][j]),tree[num(i,j)].st=Top;
    for (int i=1;i<=n;i++)
        for (int j=1;j<=n;j++)  insert(num(i,j),num(i,j+1));
    for (int i=1;i<=n;i++)
        for (int j=1;j<=n;j++)  insert(num(i,j),num(i+1,j));
    in(m);
    for (int i=1;i<=m;i++)
    {
        in(x);in(y);q[i]=(Query){(short)x,(short)y};
        for (int j=1;j<=4;j++)
        {
            int tx=x+dx[j],ty=y+dy[j];
            if (!in_size(tx,ty))    continue;
            if (a[x][y]==a[tx][ty])
                e[min(num(x,y),num(tx,ty))+(((j-1)>>1)+1)*n*n].w.push(i);
        }
        a[x][y]^=1;
    }
    for (int i=1;i<=n;i++)
        for (int j=1;j<=n;j++)
        {
            int tx=i,ty=j+1;
            if (in_size(tx,ty)&&a[i][j]==a[tx][ty]) e[num(i,j)+n*n].w.push(m+1);
            tx=i+1;ty=j;
            if (in_size(tx,ty)&&a[i][j]==a[tx][ty]) e[num(i,j)+(n*n<<1)].w.push(m+1);
        }
    for (int i=m;i;i--) a[q[i].x][q[i].y]^=1;
    for (int i=1;i<=n;i++)
        for (int j=1;j<=n;j++)  ans[a[i][j]]++;
    int cnt=0;
    for (int i=1;i<=n;i++)
        for (int j=1;j<=n;j++)
        {
            int tx=i,ty=j+1;
            if (in_size(tx,ty)&&a[i][j]==a[tx][ty]) add(num(i,j)+n*n,a[i][j]),cnt++;
            tx=i+1;ty=j;
            if (in_size(tx,ty)&&a[i][j]==a[tx][ty]) add(num(i,j)+(n*n<<1),a[i][j]),cnt++;
        }
    for (int i=1;i<=m;i++)
    {
        x=q[i].x;y=q[i].y;
        for (int j=1;j<=4;j++)
        {
            int tx=x+dx[j],ty=y+dy[j];
            if (in_size(tx,ty)&&a[x][y]==a[tx][ty]) 
                del(min(num(x,y),num(tx,ty))+(((j-1)>>1)+1)*n*n,a[x][y]);
        }
        ans[a[x][y]]--;a[x][y]^=1;ans[a[x][y]]++;
        for (int j=1;j<=4;j++)
        {
            int tx=x+dx[j],ty=y+dy[j];
            if (in_size(tx,ty)&&a[x][y]==a[tx][ty]) 
                add(min(num(x,y),num(tx,ty))+(((j-1)>>1)+1)*n*n,a[x][y]);
        }
        printf("%d %d\n",ans[1],ans[0]);
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值