原题传送门

这道题肥肠毒瘤qwqwq,我被卡了qwqwq

这题的正解好像是线段树+并查集,但由于我人丑常数大被卡成了70

#include <bits/stdc++.h>
#define N 205
#define getchar nc
using namespace std;
inline char nc(){
static char buf[100000],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline int read()
{
register int x=0,f=1;register char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
return x*f;
}
inline void write(register int x)
{
if(!x)putchar('0');if(x<0)x=-x,putchar('-');
static int sta[20];register int tot=0;
while(x)sta[tot++]=x%10,x/=10;
while(tot)putchar(sta[--tot]+48);
}
int n,m;
int a[N][N];
struct node{
int le[N],ri[N],lb[N],rb[N],s0,s1;
}t[N<<2];
int fa[N<<2],tmp[N<<2];
inline int father(register int x)
{
return fa[x]==x?x:fa[x]=father(fa[x]);
}
inline void pushup(register int x)
{
t[x].s0=t[x<<1].s0+t[x<<1|1].s0;
t[x].s1=t[x<<1].s1+t[x<<1|1].s1;
memcpy(t[x].lb,t[x<<1].lb,sizeof(t[x].lb));
memcpy(t[x].rb,t[x<<1|1].rb,sizeof(t[x].rb));
for(register int i=1;i<=n<<2;++i)
fa[i]=i;
for(register int i=1;i<=n;++i)
t[x<<1|1].le[i]+=n<<1,t[x<<1|1].ri[i]+=n<<1;
for(register int i=1;i<=n;++i)
{
int xx=t[x<<1].ri[i],yy=t[x<<1|1].le[i];
if(father(xx)!=father(yy)&&t[x<<1].rb[i]==t[x<<1|1].lb[i])
{
fa[father(xx)]=father(yy);
if(t[x<<1].rb[i])
--t[x].s1;
else
--t[x].s0;
}
}
for(register int i=1;i<=n;++i)
t[x].le[i]=father(t[x<<1].le[i]),t[x].ri[i]=father(t[x<<1|1].ri[i]);
for(register int i=1;i<=n;++i)
tmp[i<<1]=t[x].le[i],tmp[(i<<1)-1]=t[x].ri[i];
sort(tmp+1,tmp+1+(n<<1));
int maxsum=unique(tmp+1,tmp+1+(n<<1))-tmp-1;
for(register int i=1;i<=n;++i)
{
t[x].le[i]=lower_bound(tmp+1,tmp+1+maxsum,t[x].le[i])-tmp;
t[x].ri[i]=lower_bound(tmp+1,tmp+1+maxsum,t[x].ri[i])-tmp;
}
for(register int i=1;i<=n;++i)
t[x<<1|1].le[i]-=n<<1,t[x<<1|1].ri[i]-=n<<1;
}
inline void build(register int x,register int l,register int r)
{
if(l==r)
{
int tot=0;
for(register int i=1;i<=n;++i)
{
if(a[i][l]!=a[i-1][l])
{
++tot;
if(a[i][l])
++t[x].s1;
else
++t[x].s0;
}
t[x].le[i]=t[x].ri[i]=tot;
t[x].lb[i]=t[x].rb[i]=a[i][l];
}
return;
}
int mid=l+r>>1;
build(x<<1,l,mid);
build(x<<1|1,mid+1,r);
pushup(x);
}
inline void change(register int x,register int l,register int r,register int pos)
{
if(l==r)
{
int tot=0;
t[x].s0=t[x].s1=0;
for(register int i=1;i<=n;++i)
{
if(a[i][l]!=a[i-1][l])
{
++tot;
if(a[i][l])
++t[x].s1;
else
++t[x].s0;
}
t[x].le[i]=t[x].ri[i]=tot;
t[x].lb[i]=t[x].rb[i]=a[i][l];
}
return;
}
int mid=l+r>>1;
if(pos<=mid)
change(x<<1,l,mid,pos);
else
change(x<<1|1,mid+1,r,pos);
pushup(x);
}
int main()
{
n=read();
for(register int i=1;i<=n;++i)
{
a[0][i]=-1;
for(register int j=1;j<=n;++j)
a[i][j]=read();
}
build(1,1,n);
m=read();
while(m--)
{
int x=read(),y=read();
a[x][y]^=1;
change(1,1,n,y);
write(t[1].s1),putchar(' '),write(t[1].s0),puts("");
}
return 0;
}

好像珂以用lct维护连通性?

不用强制在线,我们珂以离线处理

计算每条边加入和删除的时间,就珂以用lct维护删除时间最靠后的生成树

代码(抄来的)

#include <bits/stdc++.h>
#define C 205
#define N 200005
#define getchar nc
using namespace std;
inline char nc(){
static char buf[100000],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline int read()
{
register int x=0,f=1;register char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
return x*f;
}
inline void write(register int x)
{
if(!x)putchar('0');if(x<0)x=-x,putchar('-');
static int sta[20];register int tot=0;
while(x)sta[tot++]=x%10,x/=10;
while(tot)putchar(sta[--tot]+48);
}
int dx[4]={0,0,1,-1};
int dy[4]={1,-1,0,0};
int n,m,sz;
int color[C][C],c[C][C],ans[2];
struct data{
int x,y,t,d,id,opt,c;
bool operator < (const data &a) const
{
return x<a.x||x==a.x&&y<a.y;
}
}e[N],opr[10005];
inline bool cmp(register data a,register data b)
{
return a.t<b.t||(a.t==b.t&&a.opt<b.opt);
}
map <data,int> mp;
int cnt=0;
inline int eid(register int a,register int b,register int c,register int d)
{
if(a==c)
{
if(b>d)
b^=d^=b^=d;
return (a-1)*(n-1)+b;
}
else
{
if(a>c)
a^=c^=a^=c;
return n*(n-1)+(a-1)*n+b;
}
}
int f[N],ch[N][2],minn[N],rev[N],sta[N],val[N];
int re[N],pt[N],l[N],r[N],tree[N];
inline bool isroot(register int x)
{
return ch[f[x]][0]!=x&&ch[f[x]][1]!=x;
}
inline int get(register int x)
{
return ch[f[x]][1]==x;
}
inline void update(register int x)
{
int loc=x;
if(ch[x][0])
{
if(val[minn[ch[x][0]]]<val[loc])
loc=minn[ch[x][0]];
}
if(ch[x][1])
{
if(val[minn[ch[x][1]]]<val[loc])
loc=minn[ch[x][1]];
}
minn[x]=loc;
}
inline void pushdown(register int x)
{
if(x&&rev[x])
{
if(ch[x][0])
rev[ch[x][0]]^=1;
if(ch[x][1])
rev[ch[x][1]]^=1;
ch[x][0]^=ch[x][1]^=ch[x][0]^=ch[x][1];
rev[x]=0;
}
}
inline void rotate(register int x)
{
int old=f[x],oldf=f[old],wh=get(x);
if(!isroot(old))
ch[oldf][ch[oldf][1]==old]=x;
f[x]=oldf;
ch[old][wh]=ch[x][wh^1];
if(ch[old][wh])
f[ch[old][wh]]=old;
ch[x][wh^1]=old;
f[old]=x;
update(old);
update(x);
}
inline void splay(register int x)
{
int top=0;
sta[++top]=x;
for(register int i=x;!isroot(i);i=f[i])
sta[++top]=f[i];
for(register int i=top;i;--i)
pushdown(sta[i]);
for(register int fa;!isroot(x);rotate(x))
if (!isroot(fa=f[x]))
rotate((get(x)==get(fa))?fa:x);
}
inline void access(register int x)
{
int t=0;
for(;x;t=x,x=f[x])
{
splay(x);
ch[x][1]=t;
update(x);
}
}
inline void reverse(register int x)
{
access(x);
splay(x);
rev[x]^=1;
}
inline int find(register int x)
{
access(x);
splay(x);
while(ch[x][0])
x=ch[x][0];
return x;
}
inline void link(register int x,register int y)
{
reverse(x);
f[x]=y;
}
inline void cut(register int x,register int y)
{
reverse(x);
access(y);
splay(y);
ch[y][0]=f[x]=0;
}
inline void add(register int i,register int cc)
{
int x=e[i].x,y=e[i].y,d=e[i].d,id=e[i].id;
if(find(x)==find(y))
{
reverse(x);
access(y);
splay(y);
int loc=minn[y];
if(d<=val[loc])
return;
cut(loc,l[loc]);
cut(loc,r[loc]);
tree[re[loc]]=0;
}
else
--ans[cc];
++sz;
val[sz]=d,re[sz]=id,pt[id]=sz,tree[id]=1;
l[sz]=x,r[sz]=y;
link(x,sz);
link(y,sz);
}
inline void del(register int i)
{
int x=e[i].x,y=e[i].y,id=e[i].id;
cut(x,pt[id]);
cut(y,pt[id]);
tree[id]=0;
}
int main()
{
n=read();
for(register int i=1;i<=n;++i)
for(register int j=1;j<=n;++j)
{
color[i][j]=c[i][j]=read();
++ans[c[i][j]];
}
for(register int i=1;i<=n;++i)
for(register int j=1;j<=n;++j)
{
int num=(i-1)*n+j,cc=color[i][j];
if(j!=n&&color[i][j+1]==cc)
e[++cnt].x=num,e[cnt].y=num+1,e[cnt].t=0,e[cnt].id=eid(i,j,i,j+1),e[cnt].opt=1,e[cnt].c=cc;
if(i!=n&&color[i+1][j]==cc)
e[++cnt].x=num,e[cnt].y=num+n,e[cnt].t=0,e[cnt].id=eid(i,j,i+1,j),e[cnt].opt=1,e[cnt].c=cc;
}
m=read();
for(register int i=1;i<=m;++i)
{
int x=read(),y=read();
opr[i].x=x,opr[i].y=y;
int num=(x-1)*n+y;
for(register int j=0;j<4;++j)
{
int nx=x+dx[j],ny=y+dy[j],nnum=(nx-1)*n+ny;
if(nx<=0||ny<=0||nx>n||ny>n)
continue;
if(c[x][y]==c[nx][ny])
e[++cnt].x=num,e[cnt].y=nnum,e[cnt].t=i,e[cnt].id=eid(x,y,nx,ny),e[cnt].opt=-1;
else
e[++cnt].x=num,e[cnt].y=nnum,e[cnt].t=i,e[cnt].id=eid(x,y,nx,ny),e[cnt].opt=1;
}
c[x][y]^=1;
}
sort(e+1,e+cnt+1,cmp);
for(register int i=1;i<=cnt;++i)
e[i].d=m+1;
mp.clear();
for(register int i=cnt;i>=1;--i)
{
if(e[i].x>e[i].y)
e[i].x^=e[i].y^=e[i].x^=e[i].y;
if(mp[e[i]])
e[i].d=mp[e[i]];
mp[e[i]]=e[i].t;
}
sz=n*n;
memset(val,127,sizeof(val));
int now=1;
for(;now<=cnt&&e[now].t<=0;++now)
add(now,e[now].c);
for(register int i=1;i<=m;++i)
{
int x=opr[i].x,y=opr[i].y;
int cc=color[x][y];
for(;now<=cnt&&e[now].t<=i;++now)
if(e[now].opt==-1)
{
if(!tree[e[now].id])
continue;
del(now);
++ans[cc];
}
else
add(now,cc^1);
--ans[cc],++ans[cc^1];
color[x][y]^=1;
write(ans[1]),putchar(' '),write(ans[0]),puts("");
}
return 0;
}
05-11 19:20