BZOJ1453: [Wc]Dface双面棋盘
来源:互联网 发布:js里取juid 编辑:程序博客网 时间:2024/04/30 19:16
题目
http://www.lydsy.com/JudgeOnline/problem.php?id=1453
题解
线段树上维护奇怪的信息第二题,这道题写的很快,1h,但是因为合并的时候把并查集合并写错了qwqqqq卧槽啊这个时候了我居然还在写错这些、记住是修改根的父亲为根啊(倒)。
思路还是挺简单啦,每个节点开两个200的数组记录两边的连通信息,在一个连通块的标号一样,然后合并的时候,交界处如果颜色相同就认为有一条边然后做并查集合并。并查集也是真的厉害辣,代码很简单啦(可能是被上一道题虐傻了)。
代码
//QWsin#include<cmath>#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>using namespace std;const int maxn=200+10;int col[maxn][maxn];int p[maxn*4],id[maxn*4];int findset(int x){return p[x]==x?x:p[x]=findset(p[x]);}int n;struct G{//存放连通性 int l,r; int cnt1,cnt2,T,pl[maxn],pr[maxn]; //维护连通块个数,pl左pr右并查集,T记录边界上并查集编号最大值(方便合并) //cnt1 black cnt2 white G(int l=0,int r=0):l(l),r(r){ cnt1=cnt2=0;memset(pl,0,sizeof pl); memset(pr,0,sizeof pr); } G operator + (const G &rhs)const{ G ret(l,rhs.r); int C1=cnt1+rhs.cnt1; int C2=cnt2+rhs.cnt2; for(int i=1;i<=T+rhs.T;++i) p[i]=i,id[i]=0; //右边的连通块编号统一加上左边的T值,合并为一个图再连边 for(int i=1;i<=n;++i) if(col[i][r]==col[i][r+1]) { int p1=findset(pr[i]); int p2=findset(rhs.pl[i]+T); if(p1!=p2){ p[p2]=p1;//原来把并查集这里合并写错了(捂脸) if(col[i][r]) --C1; else --C2; } } //离散一下编号,因为都不大所以可以直接用数组记离散后对应的编号 int rank=0;ret.cnt1=C1;ret.cnt2=C2; for(int i=1;i<=n;++i){ int p1=findset(pl[i]); int p2=findset(rhs.pr[i]+T); if(!id[p1]){id[p1]=++rank;} if(!id[p2]){id[p2]=++rank;} ret.pl[i]=id[p1]; ret.pr[i]=id[p2]; } ret.T=rank; return ret; } //单独更新pos列的信息 inline void work(int pos) { cnt1=cnt2=0; for(int i=1;i<=n;++i) { if(i==1||col[i][pos]!=col[i-1][pos]) { if(col[i][pos]) ++cnt1; else ++cnt2; } pl[i]=pr[i]=cnt1+cnt2; } T=cnt1+cnt2; }};struct Node{ G g; Node *lc,*rc; Node(int l,int r){lc=rc=NULL;g=G(l,r);} inline void up(){g=lc->g+rc->g;}}*root;#define mid ((l+r)>>1)void build(Node* &p,int l,int r){ p=new Node(l,r); if(l==r) {p->g.work(l);return ;} build(p->lc,l,mid); build(p->rc,mid+1,r); p->up();}void updata(Node* p,int l,int r,int pos){ if(l==r){p->g.work(l);return ;} if(pos<=mid) updata(p->lc,l,mid,pos); else updata(p->rc,mid+1,r,pos); p->up();}int main(){ cin>>n; for(int i=1;i<=n;++i) for(int j=1;j<=n;++j) scanf("%d",col[i]+j); build(root,1,n); int m,a,b;cin>>m; while(m--) { scanf("%d%d",&a,&b); col[a][b]^=1; updata(root,1,n,b); printf("%d %d\n",root->g.cnt1,root->g.cnt2);//很良心的一点就是不用写query了 } return 0;}
0 0
- BZOJ1453: [Wc]Dface双面棋盘
- bzoj1453: [Wc]Dface双面棋盘
- BZOJ1453——[Wc]Dface双面棋盘
- [BZOJ1453][Wc]Dface双面棋盘(lct)
- 【WC2005】【BZOJ1453】Dface双面棋盘
- [Wc]Dface双面棋盘
- WC 2005 dface 双面棋盘
- 1453: [Wc]Dface双面棋盘 (线段树+并茶几)
- BZOJ1453 WCDface 双面棋盘
- [CDQ分治 并查集] BZOJ 1453 [Wc]Dface双面棋盘
- BZOJ 1453 Wc2005 Dface双面棋盘 Link-Cut-Tree
- 【BZOJ】【P1453】【WC2005】【Dface双面棋盘】【题解】【线段树+并查集】
- BZOJ 1453 [WC] 双面棋盘 并查集+线段树暴搞
- bzoj 1453 双面棋盘 LCT 并查集
- wc
- wc
- wc
- wc
- python3.5以上 爬虫 (模块化)
- 常见异常以及处理问题办法
- 我的生活(四)-误打误撞入行It
- nginx try_files用法 及Nginx location的一些配置
- setTimeout与setInterval方法的区别
- BZOJ1453: [Wc]Dface双面棋盘
- 洛谷 P1160 队列安排
- utf-8编码格式
- Linux中执行shell脚本的4种方法总结
- Linux_Error_01
- redis添加到linux系统服务
- 嵌入式Linux-Proc文件系统
- Espresso安装说明
- 为什么运行之后多了\r Linux命令之dos2unix - 将DOS格式文本文件转换成UNIX格式