博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[WC2005]双面棋盘(并查集+分治)
阅读量:7239 次
发布时间:2019-06-29

本文共 2675 字,大约阅读时间需要 8 分钟。

题目描述

题解

唉,还是码力不行,写了一个多小时发现想错了又重构了一个多小时。

这道题意图很显然,动态维护联通块,有一个经典做法就是用LCT维护按照删除时间维护的最大生成树。

网上还有一种神奇的做法,线段树套并查集,蒟蒻表示不懂。。

这道题可以利用并查集操作可以撤销这种性质来做。

线段树分治

线段树分治可以分两种情况,操作之间独立和操作之间不独立。

操作之间独立意味着我先完成哪个操作就可以,例如找最优点,有。

还有一种是操作之间是可以相互影响的,比如说这道题,连通性这种东西和我加的每一条边都有关。

我们可以按时间分治,先离线找出每条边出现的时间段,把这些时间段加入线段树中,然后在线段树上dfs,进入节点时把所有边加入,删除时栈序撤销来的时候的操作(因为线段树dfs的过程也是压栈弹栈的过程,所以我们可以准确撤销操作),然后在根节点统计答案,联通块的个数为点数-边数,点数这种东西我们可以直接离线维护(我一开始傻了)。

代码

#include
#include
#include
#include
#define N 40002#define maxn 209using namespace std;int n,id[maxn][maxn],f[N],tot,ls[N<<1],rs[N<<1],b[N],bl,w[N],wl,deep[N],num,last[N<<1],m,root,a[maxn][maxn],bian;int tag[maxn][maxn][4],anti[4],color[N<<1];const int dx[4]={
0,1,-1,0};const int dy[4]={
1,0,0,-1};inline int rd(){ int x=0;char c=getchar();bool f=0; while(!isdigit(c)){
if(c=='-')f=1;c=getchar();} while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();} return f?-x:x;}int find(int x){
return f[x]==x?x:find(f[x]);}struct node{
int id,co;};struct rbs{
int dep,root,link,co;};struct node2{
int x,y;};vector
vec[N<<1];vector
zh[N<<1];node2 linko[N<<1];void upd(int &cnt,int l,int r,int L,int R,int x,int y){ if(!cnt)cnt=++tot; if(l>=L&&r<=R){vec[cnt].push_back(node{x,y});return;} int mid=(l+r)>>1; if(mid>=L)upd(ls[cnt],l,mid,L,R,x,y); if(mid
>1; solve(ls[cnt],l,mid); solve(rs[cnt],mid+1,r); } while(zh[cnt].size()){ rbs x=zh[cnt].back();zh[cnt].pop_back(); deep[x.root]=x.dep;f[x.link]=x.link; if(x.co)bl--;else wl--; }}int main(){ anti[0]=3;anti[3]=0;anti[2]=1;anti[1]=2; n=rd();int x,y; for(int i=1;i<=n;++i) for(int j=1;j<=n;++j){ a[i][j]=rd(),id[i][j]=++num; if(a[i][j])b[0]++;else w[0]++; } for(int i=1;i<=num;++i)f[i]=i,deep[i]=1; memset(last,-1,sizeof(last)); for(int i=1;i<=n;++i) for(int j=1;j<=n;++j) for(int k=0;k<2;++k){ int xx=i+dx[k],yy=j+dy[k]; if(!id[xx][yy])continue; tag[i][j][k]=tag[xx][yy][anti[k]]=++bian; if(a[i][j]==a[xx][yy])last[bian]=0,color[bian]=a[i][j]; linko[bian]=node2{id[i][j],id[xx][yy]}; } m=rd(); for(int i=1;i<=m;++i){ x=rd();y=rd();b[i]=b[i-1];w[i]=w[i-1]; if(a[x][y])b[i]--,w[i]++;else b[i]++,w[i]--; for(int k=0;k<4;++k){ int xx=x+dx[k],yy=y+dy[k],_id=tag[x][y][k]; if(!_id)continue; if(a[x][y]==a[xx][yy]) upd(root,0,m,last[_id],i-1,_id,a[x][y]),last[_id]=-1; else last[_id]=i,color[_id]=a[xx][yy]; } a[x][y]^=1; } for(int i=1;i<=n;++i) for(int j=1;j<=n;++j) for(int k=0;k<2;++k){ int xx=i+dx[k],yy=j+dy[k],_id=tag[i][j][k]; if(~last[_id])upd(root,0,m,last[_id],m,_id,color[_id]); } solve(root,0,m); return 0; }

转载于:https://www.cnblogs.com/ZH-comld/p/10165315.html

你可能感兴趣的文章
Ubuntu 14.04 安装VMware 12
查看>>
Hbase多版本的读写(Shell&Java API版)
查看>>
判断单链表是否有环的两种方法
查看>>
网页上用js禁用鼠标右键
查看>>
【&#9733;】微信之于QQ的市场哲学
查看>>
抓取某一个网站整站的记录
查看>>
Android依赖管理与私服搭建
查看>>
常用正则表达式大全!(例如:匹配中文、匹配html)
查看>>
结合抓包工具深入分析slb、vpc网络配置ftp服务
查看>>
关于db link权限分配的苦旅(二)
查看>>
CentOS7下如何查看vsftpd服务的状态
查看>>
阿里云Redis华北5 (呼和浩特)开放售卖
查看>>
SAP后台配置中“公司”与“公司代码”概念的不同
查看>>
JSP application对象
查看>>
使用消息系统进行微服务间通讯时,如何保证数据一致性
查看>>
Java---俄罗斯方块小游戏
查看>>
spring boot 调试 - 热部署
查看>>
Python installation
查看>>
管理数据中心需要瞻前顾后
查看>>
Ubuntu 搜狗输入法 双拼输入法
查看>>